使用enable_if专门设计模板方法

Mar*_*son 6 c++ templates sfinae template-specialization c++11

我正在编写一个存储a的模板类,std::function以便稍后调用它.这是简化的代码:

template <typename T>
struct Test
{
    void call(T type)
    {
        function(type);
    }
    std::function<void(T)> function;
};
Run Code Online (Sandbox Code Playgroud)

问题是该模板不能为该void类型编译,因为

void call(void type)
Run Code Online (Sandbox Code Playgroud)

变得不确定.

专门针对该void类型并不能解决问题,因为

template <>
void Test<void>::call(void)
{
    function();
}
Run Code Online (Sandbox Code Playgroud)

仍然与宣言不符call(T Type).

因此,使用C++ 11的新功能,我试过std::enable_if:

typename std::enable_if_t<std::is_void_v<T>, void> call()
{
    function();
}

typename std::enable_if_t<!std::is_void_v<T>, void> call(T type)
{
    function(type);
}
Run Code Online (Sandbox Code Playgroud)

但它不能用Visual Studio编译:

错误C2039:'type':不是'std :: enable_if'的成员

你会如何解决这个问题?

max*_*x66 2

SFINAE 不(仅)处理类/结构的模板参数。

在涉及方法模板参数的条件下处理模板方法。

所以你必须写

   template <typename U = T>
   std::enable_if_t<std::is_void<U>::value> call()
    { function(); }

   template <typename U = T>
   std::enable_if_t<!std::is_void<U>::value> call(T type)
    { function(type); } 
Run Code Online (Sandbox Code Playgroud)

或者,如果你想确定UT

   template <typename U = T>
   std::enable_if_t<   std::is_same<U, T>::value
                    && std::is_void<U>::value> call()
    { function(); }

   template <typename U = T>
   std::enable_if_t<std::is_same<U, T>::value
                    && !std::is_void<U>::value> call(T type)
    { function(type); } 
Run Code Online (Sandbox Code Playgroud)

ps:是一种类型,所以之前std::enable_if_t不需要。typename

ps2:您标记了 C++11,但您的示例使用std::enable_if_t,即 C++14,并且std::is_void_v,即 C++17