我想在模板化函数上使用完美转发来确保保留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的细微差别,我很感激别人的反馈。
这是正确和惯用的方式吗?
答案 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));
}
虽然你的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");
}