带类型限制的完美转发
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));
}
虽然你的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");
}
我想在模板函数上使用完美转发来确保保留左值或右值,但同时我想对可能的参数类型施加某些限制。
例如,假设我只想将 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));
}
虽然你的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");
}