我正在尝试更好地理解C ++ 11中的std::enable_if
,并且一直在尝试编写一个最小的示例:具有成员函数A
的类void foo()
基于类模板中T
类型的不同实现
下面的代码给出了期望的结果,但我还没有完全理解它。为什么版本V2
有效,而V1
无效?为什么"多余"是否需要输入U
?
#include <iostream>
#include <type_traits>
template <typename T>
class A {
public:
A(T x) : a_(x) {}
// Enable this function if T == int
/* V1 */ // template < typename std::enable_if<std::is_same<T,int>::value,int>::type = 0>
/* V2 */ template <typename U=T, typename std::enable_if<std::is_same<U,int>::value,int>::type = 0>
void foo() { std::cout << "\nINT: " << a_ << "\n"; }
// Enable this function if T == double
template <typename U=T, typename std::enable_if<std::is_same<U,double>::value,int>::type = 0>
void foo() { std::cout << "\nDOUBLE: " << a_ << "\n"; }
private:
T a_;
};
int main() {
A<int> aInt(1); aInt.foo();
A<double> aDouble(3.14); aDouble.foo();
return 0;
}
是否有更好的方法来实现所需的结果,即基于类模板参数实现void foo()
函数的不同实现?
答案 0 :(得分:2)
我知道这不会完全回答你的问题,但它可能会给你更多的想法和理解你如何使用std::enable_if
。
您可以使用以下内容替换您的foo成员函数,并具有相同的功能:
template<typename U=T> typename std::enable_if<std::is_same<U,int>::value>::type
foo(){ /* enabled when T is type int */ }
template<typename U=T> typename std::enable_if<std::is_same<U,double>::value>::type
foo(){ /* enabled when T is type double */ }
前段时间我对enable_if的工作方式有了很好的理解,但遗憾的是我已经忘记了它的大部分复杂性,只记得使用它的更实用的方法。
答案 1 :(得分:0)
关于第一个问题:为什么V1不起作用? SFINAE仅适用于重载分辨率 - 但是在实例化类型A的位置会导致错误,远在foo()
重载解析之前。
我想有很多可能的实现 - 最合适的取决于实际的案例。一种常见的方法是将不同模板类型的A
部分推迟到辅助类。
template <typename T>
class A_Helper;
template <>
class A_Helper<int> {
public:
static void foo( int value ){
std::cout << "INT: " << value << std::endl;
}
};
template <>
class A_Helper<double> {
public:
static void foo( double value ){
std::cout << "DOUBLE: " << value << std::endl;
}
};
template <typename T>
class A {
public:
A( T a ) : a_(a)
{}
void foo(){
A_Helper<T>::foo(a_);
}
private:
T a_;
};
A
的其余部分只能以通用方式声明一次 - 只有不同的部分才会被推迟到帮助程序。根据您的要求,有很多可能的变化......