I would like to use perfect forwarding on a templated function to ensure l-valuedness or r-valuedness is preserved, but at the same time I would like to impose certain restrictions on the possible parameter types.
Suppose for example I just want to restrict T
to a callable object. The following approach looks correct to me
template<typename T>
typename std::enable_if<std::is_callable<T>>::value>::type myFun(T&& val)
{
foo(std::forward<T>(val));
}
but since I am still not yet fully comfortable with the various SFINAE nuances I would appreciate someone else's feedback.
Would this be the correct and idiomatic way to go about it?
std::is_callable
is a C++17 feature, by the way.
Anyhow, since your function myFun
doesn't return anything, it's a little weird to put the enable_if
as the return value. 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));
}
Although it would be a little bit strange for your enable_if
to exist in a vacuum. At the very least, we should catch all the types that don't fit in and provide the user with a good compiler error via 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");
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.