C++ 多线程和传递模板参数 <typename T>(T arg)

C++ multithreading and passing templated arguments <typename T>(T arg)

我有这段代码,没有任何问题:

void function_exit(dispatcher& d) { /* .. */ }
// ...
std::thread th(function_exit, std::ref(main_disp));
th.detach();

现在我尝试创建另一个 class,其中包含 std::thread,这会在编译时产生错误

thread_control mtc;
mtc.create<dispatcher&>(function_exit, main_disp);

这里是创建函数:(请阅读描述问题的注释文本)

template<typename Arg>
inline bool thread_control::create(void(*function)(Arg), Arg value)
{
    bool ok = false;
    if (created == false)
    {
        created = true;
        if (typeid(Arg).hash_code() == typeid(void).hash_code())
        {
            // this produce thread(50,5): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)'
            // type_traits(1583): message : see declaration of 'std::invoke'
            // thread(50,5): message : With the following template arguments:
            // thread(50,5): message : '_Callable=void (__cdecl *)(Arg)'
            m_thread = std::thread(function);
        }
        else
        {
            if (std::is_reference<Arg>::value)
            {
                // if only this function is used, program is compiled without errors and runs without problem.
                // (when i comment functions which are problematic and this function is uncomented)
                m_thread = std::thread(function, std::ref(value)); 
            }
            else
            {
                // this function produce this errors:
                // 2>...\Visual Studio 2019\VC\Tools\MSVC.28.29910\include\thread(65): message : see reference to function template instantiation 'unsigned int (__stdcall *std::thread::_Get_invoke<_Tuple,0,1>(std::integer_sequence<size_t,0,1>) noexcept)(void *)' being compiled
                // thread(50,5): error C2893: Failed to specialize function template 'unknown-type std::invoke(_Callable &&,_Ty1 &&,_Types2 &&...) noexcept(<expr>)'
                // type_traits(1589): message : see declaration of 'std::invoke'
                // thread(50,5): message : With the following template arguments:
                // thread(50,5): message : '_Callable=void (__cdecl *)(Arg)'
                // thread(50,5): message : '_Ty1=dispatcher'
                // thread(50,5): message : '_Types2={}'
                // thread(50,5): error C2780: 'unknown-type std::invoke(_Callable &&) noexcept(<expr>)': expects 1 arguments - 2 provided
                // type_traits(1583): message : see declaration of 'std::invoke'
                m_thread = std::thread(function, value);
            }
        }
        ok = true;
    }
    return ok;
}

我的 m_thread = std::thread(...); 函数有什么问题会抛出这些编译错误?或者我做错了什么?

 if (std::is_reference<Arg>::value)

对于给定的 Arg,这当然会计算为 truefalse

然而两者这个条件为真时执行的代码,和这个条件为假时执行的代码必须是有效的 C++.

 m_thread = std::thread(function, value);

如果 Arg 是引用,则这不是有效的 C++。即使 if 条件的计算结果为 true,并且不会执行,这个 仍然必须是有效的 C++.

此处可以使用两种基本方法。

  1. 在 C++17 及更高版本中使用 if constexpr

  2. 使用 C++14 及更早版本,您需要重写整个内容以使用特化(整个模板函数的特化,或者将相关逻辑移动到模板 类 中并特化他们)。