带类型限制的完美转发

Perfect forwarding with type restrictions

我想在模板函数上使用完美转发来确保保留左值或右值,但同时我想对可能的参数类型施加某些限制。

例如,假设我只想将 T 限制为可调用对象。 以下方法在我看来是正确的

template<typename T>
typename std::enable_if<std::is_callable<T>>::value>::type myFun(T&& val) 
{
    foo(std::forward<T>(val));
} 

但由于我对 SFINAE 的各种细微差别仍不完全满意,我将不胜感激其他人的反馈。

这是正确的惯用方法吗?

顺便说一下,

std::is_callable 是 C++17 的特性。

无论如何,由于您的函数 myFun 没有 return 任何东西,因此将 enable_if 作为 return 值有点奇怪。 Yeah, it'll become void when the template is selected, but it's probably more legible to place it as a default template argument:

template<typename T, std::enable_if_t<std::is_callable_v<T()>, int> = 0>
void myFun(T&& val) 
{
    foo(std::forward<T>(val));
}

Demo

虽然你的enable_if存在于真空中会有点奇怪。至少,我们应该捕获所有不适合的类型,并通过 static_assert:

为用户提供良好的编译器错误
template<typename T, std::enable_if_t<std::is_callable_v<T()>, int> =0>
void myFun(T&& val) 
{
    foo(std::forward<T>(val));
}

template<typename T, std::enable_if_t<!std::is_callable_v<T()>, int> =0>
void myFun(T&& val) 
{
    static_assert(sizeof(T) == 0, "myFun is only callable with an argument that can be called as a function with no params");
}

Demo2