enable_if 添加具有默认参数的函数参数?
enable_if to Add a function parameter that has a default argument?
我无法理解呈现的第二种情况 here。它说:
•Scenario 2: Adding a function parameter that has a default argument:
template <your_stuff> your_return_type_if_present
yourfunction(args, enable_if_t<your condition, FOO> = BAR) {
// ...
}
Scenario 2 leaves the parameter unnamed. You could say ::type Dummy = BAR
, but the name Dummy is irrelevant, and giving it a name is likely to trigger an unreferenced parameter warning. You have to choose a FOO
function parameter type and BAR
default argument. You could say int
and 0
, but then users of your code could accidentally pass to the function an extra integer that would be ignored. Instead, we recommend that you use void **
and either 0
or nullptr
because almost nothing is convertible to 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;
}
enable_if
示例(如果有帮助):
对于具有非空 return 类型的函数:
单一条件:
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 return 类型的函数:
单一条件:
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>
Microsoft 的文档 there
那里清澈如泥。请改用 this。
为函数模板提供未命名的默认参数,格式为:
typename enable_if<your_condition, void **>::type = nullptr
(正如 MS 抄写员所建议的),在您希望的情况下很有用 - 并且仅在情况下 -
编写具有不同行为的函数模板的多个重载
由一个或多个模板参数控制。然后,通过
用表达适当条件的条件替换 your_condition
对模板参数的要求,您可以使用 SFINAE
原则 select 您要为其实例化的特定重载
给定模板参数。
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
编译失败。这是模板解析中的替换失败。代入
在平方重载中 T
的 int
不可行 。所以平方超载是
从运行中剔除,只剩下加倍重载实例化
函数调用。
当 T
是(比如)double
而不是 int
时,则恰恰相反
并且只有平方重载在模板解析中幸存下来。致电 foo(2)
你得到加倍。调用 foo(3.3)
即可得到平方。
此处MS的标本SFINAE参数冗长。
template< bool B, class T = void >
struct enable_if;
根据 C++11 标准及更高版本,默认 T
为 void
。所以像:
typename std::enable_if<some_condition, void **>::type = nullptr
也可以缩写为:
typename std::enable_if<some_condition>::type * = nullptr
从 C++14 开始,标准有:
template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type
所以同一个SFINAE参数可以进一步缩短为:
std::enable_if_t<some_condition> * = nullptr
将 SFINAE 函数模板参数应用于您在
post,你会这样写:
enum ops {
add,
multiply
};
template<ops Op>
int op(int const & lhs, int const & rhs,
std::enable_if_t<Op == add> * = nullptr)
{
return lhs + rhs;
}
template<ops Op>
int op(int const & lhs, int const & rhs,
std::enable_if_t<Op == multiply> * = nullptr)
{
return lhs * rhs;
}
...
auto i = op<add>(2,3);
auto j = op<multiply>(2,3);
...
// C++14
我无法理解呈现的第二种情况 here。它说:
•Scenario 2: Adding a function parameter that has a default argument:
template <your_stuff> your_return_type_if_present
yourfunction(args, enable_if_t<your condition, FOO> = BAR) {
// ...
}
Scenario 2 leaves the parameter unnamed. You could say
::type Dummy = BAR
, but the name Dummy is irrelevant, and giving it a name is likely to trigger an unreferenced parameter warning. You have to choose aFOO
function parameter type andBAR
default argument. You could sayint
and0
, but then users of your code could accidentally pass to the function an extra integer that would be ignored. Instead, we recommend that you usevoid **
and either0
ornullptr
because almost nothing is convertible tovoid **
:
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;
}
enable_if
示例(如果有帮助):
对于具有非空 return 类型的函数:
单一条件:
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 return 类型的函数:
单一条件:
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>
Microsoft 的文档 there 那里清澈如泥。请改用 this。
为函数模板提供未命名的默认参数,格式为:
typename enable_if<your_condition, void **>::type = nullptr
(正如 MS 抄写员所建议的),在您希望的情况下很有用 - 并且仅在情况下 -
编写具有不同行为的函数模板的多个重载
由一个或多个模板参数控制。然后,通过
用表达适当条件的条件替换 your_condition
对模板参数的要求,您可以使用 SFINAE
原则 select 您要为其实例化的特定重载
给定模板参数。
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
编译失败。这是模板解析中的替换失败。代入
在平方重载中 T
的 int
不可行 。所以平方超载是
从运行中剔除,只剩下加倍重载实例化
函数调用。
当 T
是(比如)double
而不是 int
时,则恰恰相反
并且只有平方重载在模板解析中幸存下来。致电 foo(2)
你得到加倍。调用 foo(3.3)
即可得到平方。
此处MS的标本SFINAE参数冗长。
template< bool B, class T = void >
struct enable_if;
根据 C++11 标准及更高版本,默认 T
为 void
。所以像:
typename std::enable_if<some_condition, void **>::type = nullptr
也可以缩写为:
typename std::enable_if<some_condition>::type * = nullptr
从 C++14 开始,标准有:
template< bool B, class T = void >
using enable_if_t = typename enable_if<B,T>::type
所以同一个SFINAE参数可以进一步缩短为:
std::enable_if_t<some_condition> * = nullptr
将 SFINAE 函数模板参数应用于您在 post,你会这样写:
enum ops {
add,
multiply
};
template<ops Op>
int op(int const & lhs, int const & rhs,
std::enable_if_t<Op == add> * = nullptr)
{
return lhs + rhs;
}
template<ops Op>
int op(int const & lhs, int const & rhs,
std::enable_if_t<Op == multiply> * = nullptr)
{
return lhs * rhs;
}
...
auto i = op<add>(2,3);
auto j = op<multiply>(2,3);
...
// C++14