我无法理解提出的第二种情况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
默认参数。您可以说int
和0
,但是代码的用户可能会意外地向该函数传递一个可忽略的额外整数。相反,我们建议您使用void **
以及0
或nullptr
,因为几乎所有内容都无法转换为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;
}
答案 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对齐
参数用于确定将实例化倍增过载
如果T
为int
,则会选择平方超载。
当T
为int
时,条件为:
!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>