完美转发类型限制

时间:2017-01-17 13:59:11

标签: c++ c++11 sfinae perfect-forwarding

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

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

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

但由于我还不熟悉各种SFINAE的细微差别,我很感激别人的反馈。

这是正确和惯用的方式吗?

1 个答案:

答案 0 :(得分:3)

顺便说一下,

std::is_callable是一个C ++ 17的功能。

无论如何,由于您的函数myFun没有返回任何内容,因此将enable_if作为返回值会有点奇怪。是的,当选择模板时,它会变为void,但将它作为默认模板参数放置可能更为清晰:

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