如果自由功能不存在,则SFINAE从过载设置中删除功能

时间:2016-11-16 14:26:44

标签: c++ c++11

如果不存在特定的自由函数,从重载集中删除模板函数的规范方法是什么。所以我有一个功能

template <typename T> void foo( T t )
{
    // Do stuff
}

如果一个自由函数采用类型为T的参数,我想从重载集中删除它,比如说

bar( T )

不存在。

如果自由函数确实存在,那么如何从重载中删除一个函数。如果功能栏确实存在,请删除上面的函数foo?

3 个答案:

答案 0 :(得分:4)

像这样的简单表达式可以很容易地与decltype一起使用SFINAE:

template <typename T>
auto foo( T t ) -> decltype(bar(t), void())
{
    // Do stuff
}

答案 1 :(得分:2)

Date()

这为我们提供了一个特征namespace details { template<template<class...>class Z, class, class...Ts> struct can_apply:std::false_type{}; template<template<class...>class Z, class...Ts> struct can_apply<Z, std::void_t<Z<Ts...>>, Ts...>:std::true_type{}; }; template<template<class...>class Z, class...Ts> using can_apply = details::can_apply<Z, void, Ts...>; template<class T> using bar_r = decltype( bar( std::declval<T>() ) ); template<class T> using can_bar = can_apply<bar_r, T>; can_bar iff true是一个有效的表达式。

bar(t)

的优点是SFINAE不会弄乱template<class T> std::enable_if_t< can_bar<T>{}, int> =0 > void foo( T t ) {} 函数的明显签名。反之亦然:

foo

这种技术的另一个优点。

请注意,如果您在左值上下文中调用它而不是转发它,则可能需要template<class T> std::enable_if_t< !can_bar<T>{}, int> =0 > void foo( T t ) {} 而不是can_bar<T&>

上面的一些内容超出了C ++ 11。

它使用T的C ++ 14功能。在C ++ 11中将enable_if_t替换为enable_if_t<blah>,或者编写自己的typename enable_if<blah>::type

它还使用enable_if_t的C ++ 14功能。

std::void_t

用C ++ 11编写。

template<class...>struct voider{using type=void;}; template<class...Ts>using void_t = typename voider<Ts...>::type; ,跟C ++ 20一样,与上面的is_detected类似。

答案 2 :(得分:1)

template <typename T, typename = decltype( bar( std::declval<T>() ), void() ) >
void foo( T t )
{
    // Do stuff
}