简体   繁体   中英

Perfect forwarding with type restrictions

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));
}

Demo

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");
}

Demo2

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM