c++ - 表达式 sfinae 中的惯用回退

标签 c++ c++11 sfinae function-prototypes

Expression SFINAE是一种非常方便的方法,可以编写多个替代函数来做同一件事,然后选择最好的一个进行编译。您在函数原型(prototype)中提到了关键表达式,如果它们无效,则原型(prototype)将被忽略,并有望选择另一个。

这很方便,除了为表达式未定义的情况声明原型(prototype)。通常原型(prototype)集必须划分为互斥域,因为从重载决议的角度来看它们可能是相等的,并且允许两个进入重载集会导致歧义。

总是可以为给定的表达式定义一个老式的特征类型,以与 std::enable_if 一起使用:

template< typename s, typename t, typename u, typename = void >
struct is_product_serializable : std::false_type {};

template< typename s, typename t, typename u >
struct is_product_serializable< s, t, u, typename std::conditional< true, void,
   decltype( std::declval< s >() << std::declval< t >() * std::declval< u >() )
>::type >
    : std::true_type {};

如果不是因为需要从 false_type 派生某些东西,std::conditional 可以直接进入函数原型(prototype),所有这些样板都可以离开。

还有其他选择吗?也许有某种方法可以降低不干扰类型推导的函数重载的级别?

最佳答案

一种替代方法是添加一个调度程序函数,该函数添加一个虚拟参数,如标签,用于摆动空间以使参数列表不同。

// "Primary" template is just a dispatcher
template< typename ... args >
void chuck( args && ... rem ) {
    return chuck_impl( 0, std::forward< args >( a ) ... );
}

// preferred alternative matches int to 0 but is controlled by SFINAE
template< typename t, typename u, typename ... args >
auto chuck_impl( int, t && a, u && b, args && ... rem )
-> typename std::conditional< true, void, decltype( blah( a, rem ... ) * b ) >::type {
    blah( a, rem ... ) * b;
}

// fallback requires int => float conversion
template< typename t, typename u, typename ... args >
void chuck_impl( float, t && a, u && b, args && ... rem ) {
    bleh( a + chuck_impl( b, rem ... ) );
}

关于c++ - 表达式 sfinae 中的惯用回退,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14949518/

相关文章:

c++ - 基类成员函数的所有重载都可以被单个模板化成员函数覆盖和转发吗?

c++ - 表达式 SFINAE : how to select template version based on whether type contains a function with one or more arguments

c++ - 初始化引用时避免按值复制

c++ - set_union 和 set_intersection 的问题 - C++

C++同时输入输出到控制台窗口

c++ - 好的 C++11 信息,除了维基百科?

c++ - 如何在MFC 的CScrollView 类中制作不可见的滚动条?

c++ - std::move 的未定义行为

c++ - 我似乎无法使用 enable_if 实例化类特化

c++ - 基于依赖类型的存在重载