Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/fsharp/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 表达sfinae时的惯用回退_C++_C++11_Sfinae_Function Prototypes - Fatal编程技术网

C++ 表达sfinae时的惯用回退

C++ 表达sfinae时的惯用回退,c++,c++11,sfinae,function-prototypes,C++,C++11,Sfinae,Function Prototypes,是一种非常方便的方法,可以编写多个替代函数来完成相同的任务,并选择编译的最佳函数。您在函数原型中提到了关键表达式,如果它们无效,则会忽略原型,并有望选择另一个 这非常方便,除了在表达式未定义的情况下声明原型之外。通常,原型集必须划分为相互排斥的域,因为从过载分辨率的角度来看,它们可能是相等的,允许两个原型进入过载集中会导致歧义 人们总是可以为给定的表达式定义一个老式的特征类型,用于std::enable_if: template< typename s, typename t, typen

是一种非常方便的方法,可以编写多个替代函数来完成相同的任务,并选择编译的最佳函数。您在函数原型中提到了关键表达式,如果它们无效,则会忽略原型,并有望选择另一个

这非常方便,除了在表达式未定义的情况下声明原型之外。通常,原型集必须划分为相互排斥的域,因为从过载分辨率的角度来看,它们可能是相等的,允许两个原型进入过载集中会导致歧义

人们总是可以为给定的表达式定义一个老式的特征类型,用于
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 {};
模板
结构是可序列化的:std::false_type{};
模板
结构是可序列化的()()*std::declval())
>::类型>
:std::true_type{};
如果不是因为需要从
false\u type
派生一些东西,那么
std::conditional
可以直接进入函数原型,所有这些样板文件都会消失


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

一种替代方法是添加一个调度函数,该函数为wiggle room添加一个伪参数,如标记,以使参数列表不同

// "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 ... ) );
}
/“主”模板只是一个调度程序
模板<类型名。。。args>
无效卡盘(参数和…rem){
返回chuck_impl(0,std::forward(a)…);
}
//首选备选方案将int与0匹配,但由SFINAE控制
模板
自动卡盘(int、t&a、u&b、ARG&rem)
->typename std::conditional::type{
等等(a,rem…)*b;
}
//回退需要int=>float转换
模板
无效执行(浮动、t&a、u&b、参数和…rem){
bleh(a+chuck_impl(b,rem…);
}

我还没有完全理解这个问题。为什么你不能把这些条件放在函数原型上?你说“如果不是因为需要从
false\u type
”派生:为什么需要这样做?只有当您想使用标记分派时才是这种情况,但您不是被迫这样做的。为什么不能使用像
typename这样的启用_if@AndyProwl您指定了一个条件。相反的情况如何?您也可以将SFINAE清理为decltype((blah(a,rem…)*b),void())
@Xeo在GCC中唯一可靠的工作是
std::conditional
。我厌倦了尝试其他选择。一个更干净的版本是
decltype(void)(blah(A,rem…)*b))
。一个版本工作和另一个版本不工作是没有意义的,它们都使用相同的机制,即如果
decltype
中的表达式格式不正确,您会得到一个软错误。@Xeo,即一种机制不一定会将从a到B的所有路径视为相等。这个问题可能与