enable_if添加一个具有默认参数的函数参数?

时间:2015-03-13 19:04:36

标签: c++ sfinae enable-if

我无法理解提出的第二种情况here。它说:

  

•场景2:添加具有默认参数的函数参数:

template <your_stuff> your_return_type_if_present
yourfunction(args, enable_if_t<your condition, FOO> = BAR) {
    // ...
}
  

场景2使参数未命名。您可以说::type Dummy = BAR,但名称​​ Dummy 无关紧要,并为其命名可能会触发未引用参数警告。您必须选择FOO函数参数类型和BAR默认参数。您可以说int0,但是代码的用户可能会意外地向该函数传递一个可忽略的额外整数。相反,我们建议您使用void **以及0nullptr,因为几乎所有内容都无法转换为void **

template <your_stuff> your_return_type_if_present 
yourfunction(args, typename enable_if<your_condition, void **>::type=nullptr) {
 // ...
}

如果方案2使参数未命名,那么它可以使用什么? 有没有办法让这样的代码与enable_if一起使用?

enum otype {oadd,omull};
template<otype o>
int add(int num1, std::enable_if<o == oadd, int>::type int= num2)
{
    if (o == omull) return num1 * num1;
    if (o == oadd ) return num1 + num2;
 }

2 个答案:

答案 0 :(得分:8)

Microsoft的文档there 泥土一样清晰。请改用this

为函数模板提供以下形式的未命名默认参数:

typename enable_if<your_condition, void **>::type = nullptr

(正如MS抄写员所建议的那样),在案件中是有用的 - 只有在你想要的情况下 - 用不同的行为编写函数模板的多个重载 由一个或多个模板参数控制。然后,通过 用表达适当条件的条件替换your_condition 对模板参数的要求,您可以登记SFINAE 原则,选择要实例化的特定重载 给出模板参数。

SFINAE参数 - 我们称之为 - 是 实例化函数未使用;它仅用于在功能模板中激发SFINAE 超载分辨率。因此它可以是无名的,因此它必须是默认的: 你不能强迫你提供额外的,无用的论据 调用函数模板。

例如:

#include <type_traits>
#include <iostream>

template <typename T>
T foo(T && t, 
    typename std::enable_if<std::is_same<T,int>::value, void **>::type = nullptr)
{
    std::cout << "Doubling " << t << " gives " << (t + t) << std::endl;
    return t + t; 
}

template <typename T>
T foo(T && t, 
    typename std::enable_if<!std::is_same<T,int>::value, void **>::type = nullptr)
{
    std::cout << "Squaring " << t << " gives " << (t * t) << std::endl;
    return t * t; 
}

using namespace std;

int main()
{
    cout << foo(2) << endl;
    cout << foo(3.3) << endl;
    return 0;
}

输出是:

Doubling 2 gives 4
4
Squaring 3.3 gives 10.89
10.89

在函数模板foo的这两个重载中,第一个重载它的两倍 键入T参数,第二个参数与其参数和SFINAE对齐 参数用于确定将实例化倍增过载 如果Tint,则会选择平方超载。

Tint时,条件为:

!std::is_same<T,int>::value

控制平方过载的SFINAE参数是错误的。所以 类型说明符:

typename std::enable_if<!std::is_same<T,int>::value, void **>::type = nullptr

无法编译。这是模板解析中的替换失败。代 平方超载中int的{​​{1}} 不可行。所以平方超载是 从运行中消除,只有倍增的重载才能实例化 函数调用。

T是(比方说)T而不是double时,恰恰相反 只有平方过载才能保持模板分辨率。致电int 你会倍增拨打foo(2),即可获得平局。

MS的样本SFINAE参数在这里是不必要的冗长。

foo(3.3)

根据C ++ 11 Standard及更高版本,默认为template< bool B, class T = void > struct enable_if; T。如此:

void

也可以缩写为:

typename std::enable_if<some_condition, void **>::type = nullptr

从C ++ 14开始,标准有:

typename std::enable_if<some_condition>::type * = nullptr

因此,相同的SFINAE参数可以进一步缩短为:

template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type

将SFINAE功能模板参数应用于您手势中的手势 发帖,你会写出类似的:

std::enable_if_t<some_condition> * = nullptr

答案 1 :(得分:4)

enable_if示例(如果有帮助):

对于具有非void返回类型的函数:

对于单一条件:

template <template T, typename std::enable_if<!std::is_same<T,std::string>::value>::type* = nullptr >
T func(T x){}

对于多种情况:

template <template T, typename std::enable_if<!std::is_same<T,std::string>::value &&!std::is_same<T,int>::value>::type* = nullptr >
T func(T x){}

<小时/> 对于具有void返回类型的函数:

对于单一条件:

template <template T>
typename std::enable_if<!std::is_same<T,std::string>::value>::type
func(T x){}

对于多种情况:

template <template T>
typename std::enable_if<!std::is_same<T,std::string>::value &&!std::is_same<T,int>::value>::type
func(T x){}

不要忘记包含#include <type_traits>