c++ 检查函数参数值是否是线程本地的

vqlkdk9b  于 11个月前  发布在  其他
关注(0)|答案(2)|浏览(61)

在C++中,是否可以检查(最好在编译时)函数参数引用值是否是线程本地的?
例如

void foo( int& bar ) { ... }

字符串
我想检查/强制该酒吧引用一个thread_local。
假设在Windows和/或Fedora上使用C++17或更高版本。

rlcwz9us

rlcwz9us1#

不,你不能在编译时检查。但是,你可以做一些事情,至少文档意图,并做一些编译时检查,像这样(让类型系统为你做一些工作):

#include <iostream>

// Declare/define a class that can behave stand in for type_t
// but also describes intent
// more constructors/destructors might need to be added... this is just a sketch
template<typename type_t>
class thread_local_t
{
public:
    explicit thread_local_t(const type_t& value) :
        m_value{value}
    {
    }

    operator type_t&() noexcept
    {
        return m_value;
    }

    operator const type_t&() const noexcept
    {
        return m_value;
    }

private:
    type_t m_value;
};

// accept only a thread_local_t<int> (decorated) int
// since thread_local_t is not implicitly convertible from int
// this adds an extra compile time barrier
int foo(const thread_local_t<int>& value)
{
    std::cout << value;
    return value;
}

int main()
{
    thread_local thread_local_t<int> value{42}; // <== create a thread_local "int" here
    auto retval = foo(value);
    // foo(42);  <== will not compile
    return retval;
}

字符串

guz6ccqo

guz6ccqo2#

template<class T, auto Key>
struct thread_local_decl_t;

template<class T>
struct thread_local_t {
  template<class, auto>
  friend struct thread_local_decl_t;
  operator T&() noexcept {
    return get();
  }
  operator T const&() const noexcept {
    return get_const();
  }
private:
  T&(*gettor)() = nullptr;
  thread_local_t(T&(*gettor_arg)()):
    gettor(gettor_arg)
  {}
  T& get() { return gettor(); }
  T const& get_const() const { return gettor(); }
};
template<class T, auto Key>
struct thread_local_decl_t:
  thread_local_t<T>
{
public:
  static T& get_ctor(std::function<T()> ctor) {
    thread_local T t{ctor()};
    return t;
  }
  static T& get() {
    return get_ctor(nullptr);
  }
  static T const& get_const() {
    return get(nullptr);
  }
  template<class...Args>
  explicit thread_local_decl_t(Args&&...args):
    thread_local_t<T>(&thread_local_decl_t::get) 
  {
    // construct the thread-local
    get_ctor( [&]()->T{ return T(std::forward<Args>(args)...); } );
  }
  thread_local_decl_t(thread_local_decl_t const&)=default;
  thread_local_decl_t(thread_local_decl_t &&)=default;

};

#define THREAD_LOCAL(...) \
  thread_local_decl_t< __VA_ARGS__, []{} >

void print( thread_local_t<int> x ) {
  std::cout << x << "\n";
}

void test() {
  auto tl_int = THREAD_LOCAL(int)( 7 );
  print(tl_int);
}
int main() {
  test();
}

字符串
这个邪恶的东西使用lambda在thread_local_decl_t中创建了一个线程本地对象,这个对象对于每个使用站点都是唯一的。2我们可以传递线程本地值,并通过执行thread_local_t<int>来验证它们确实是C++类型系统的线程本地对象。
thread_local_t<X>是对线程本地值的引用,而auto name = THREAD_LOCAL(X)(construction arguments)使用此系统声明线程本地值。
需要c++20

相关问题