重载函数不编译的简单 SFINAE 示例
simple SFINAE example to overload function not compiling
我指的是这个例子SFINAE example,
我试过运行样本,
//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
using type = T;
};
template <typename T>
void do_stuff(typename enable_if<std::is_integral<T>::value, T>::type &t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
void do_stuff(typename enable_if<std::is_class<T>::value, T>::type &t) {
std::cout<<"Class selected " <<std::endl;
}
int main()
{
int t =25;
do_stuff(t);
return 0;
}
但是编译不了,请问为什么?
这对我有用:
template <typename T>
typename enable_if<std::is_integral<T>::value, void>::type
do_stuff(T& t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
typename enable_if<std::is_class<T>::value, void>::type
do_stuff(T& t) {
std::cout<<"Class selected " <<std::endl;
}
问题是 enable_if
静态调用应用于函数参数而不是 return 类型。
But this wont compile, may I know why?
因为调用do_stuff()
类型T
不能通过enable_if
推导出来。
但是如果你调用 do_stuff()
说明类型 T
int t =25;
do_stuff<int>(t); // compile
为避免此问题,我建议您使用 Nicolas Tisserand (+1) 提出的解决方案(无需将 void
解释为 enable_if
的第二个参数,因为这是默认设置)
template <typename T>
typename enable_if<std::is_integral<T>::value>::type
do_stuff(T& t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
typename enable_if<std::is_class<T>::value>::type
do_stuff(T& t) {
std::cout<<"Class selected " <<std::endl;
}
通过 return 类型启用 SFINAE。
这样就可以从参数中推导出类型 T
,因此您无需对其进行解释。
除了其他解决方案之外,如果您不希望 enable_if
作为 return 值,您可以将其作为参数类型传递,然后作为函数签名的一部分:
#include <type_traits>
#include <iostream>
//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
using type = int; // must be a non-type template parameter
};
template <typename T, typename enable_if<std::is_integral<T>::value, T>::type = 0>
void do_stuff(T &t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T, typename enable_if<std::is_class<T>::value, T>::type = 0>
void do_stuff(T &t) {
std::cout<<"Class selected " <<std::endl;
}
class Foo
{
public:
Foo() = default;
};
int main()
{
int t =25;
Foo f;
do_stuff(t);
do_stuff(f);
return 0;
}
我指的是这个例子SFINAE example,
我试过运行样本,
//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
using type = T;
};
template <typename T>
void do_stuff(typename enable_if<std::is_integral<T>::value, T>::type &t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
void do_stuff(typename enable_if<std::is_class<T>::value, T>::type &t) {
std::cout<<"Class selected " <<std::endl;
}
int main()
{
int t =25;
do_stuff(t);
return 0;
}
但是编译不了,请问为什么?
这对我有用:
template <typename T>
typename enable_if<std::is_integral<T>::value, void>::type
do_stuff(T& t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
typename enable_if<std::is_class<T>::value, void>::type
do_stuff(T& t) {
std::cout<<"Class selected " <<std::endl;
}
问题是 enable_if
静态调用应用于函数参数而不是 return 类型。
But this wont compile, may I know why?
因为调用do_stuff()
类型T
不能通过enable_if
推导出来。
但是如果你调用 do_stuff()
说明类型 T
int t =25;
do_stuff<int>(t); // compile
为避免此问题,我建议您使用 Nicolas Tisserand (+1) 提出的解决方案(无需将 void
解释为 enable_if
的第二个参数,因为这是默认设置)
template <typename T>
typename enable_if<std::is_integral<T>::value>::type
do_stuff(T& t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T>
typename enable_if<std::is_class<T>::value>::type
do_stuff(T& t) {
std::cout<<"Class selected " <<std::endl;
}
通过 return 类型启用 SFINAE。
这样就可以从参数中推导出类型 T
,因此您无需对其进行解释。
除了其他解决方案之外,如果您不希望 enable_if
作为 return 值,您可以将其作为参数类型传递,然后作为函数签名的一部分:
#include <type_traits>
#include <iostream>
//enable_if
template<bool, typename T = void>
struct enable_if {};
template <typename T>
struct enable_if<true, T> {
using type = int; // must be a non-type template parameter
};
template <typename T, typename enable_if<std::is_integral<T>::value, T>::type = 0>
void do_stuff(T &t) {
std::cout<< "Integral selected "<<std::endl;
}
template <typename T, typename enable_if<std::is_class<T>::value, T>::type = 0>
void do_stuff(T &t) {
std::cout<<"Class selected " <<std::endl;
}
class Foo
{
public:
Foo() = default;
};
int main()
{
int t =25;
Foo f;
do_stuff(t);
do_stuff(f);
return 0;
}