专攻模板类构造函数 [英] specialize a template class constructor
问题描述
我想专门研究模板类的构造函数:
I want to specialize a template class constructor:
如果类型为 int ,则默认值为 50 -50 。并且如果是float,则默认值为 0.5 和 -0.5 。
If type is int default value is 50 and -50. and if it's float default should be 0.5 and -0.5 .
我的代码是:
#include <iostream>
#include <limits>
#include <type_traits>
template<typename T>
class Foo{
public:
template<typename = typename std::enable_if<
std::is_integral<T>::value&& !std::is_floating_point<T>::value>::type>
Foo(T value1 = 50, T value2 = -50) :value1_(value1), value2_(value2){}
template<typename = typename std::enable_if<
std::is_floating_point<T>::value>::type>
Foo(T value1 = 0.5, T value2 = -0.5, void* dummy = 0) : value1_(value1), value2_(value2){}
T value1_, value2_;
};
int main()
{
Foo<float> test;
std::cout << test.value1_ << " " << test.value2_ << '\n';
Foo<int> test2;
std::cout << test2.value1_ << " " << test2.value2_;
}
但是 gcc 4.9.2拒绝了:
main.cpp: In instantiation of 'class Foo<float>':
main.cpp:29:13: required from here
main.cpp:19:3: error: no type named 'type' in 'struct std::enable_if<false, void>'
Foo(T value1 = 50, T value2 = -50) :value1_(value1), value2_(value2){}
^
main.cpp: In instantiation of 'class Foo<int>':
main.cpp:32:11: required from here
main.cpp:23:3: error: no type named 'type' in 'struct std::enable_if<false, void>'
Foo(T value1 = 0.5, T value2 = -0.5, void* dummy = 0) : value1_(value1), value2_(value2){}
^
我的代码错误吗?如果可以的话,Visual Studio为什么要编译呢?还是可能是gcc错误?!
Is my code wrong? if so why visual studio compile it ? or maybe it's a gcc bug ?!
推荐答案
您的代码不正确。顶级 T
不能在SFINAE上下文中使用其方法,这就是您要尝试的方法。只有立即发生的替换才可能导致推论失败(第14.8.2 / 8节):
Your code is incorrect. The top-level T
cannot be used in a SFINAE context for its methods, which is what you are trying to do. Only a substitution that takes place in an immediate context may result in a deduction failure (§14.8.2/8):
仅无效类型函数类型及其模板参数类型的立即上下文中的表达式可能会导致推论失败。 [注意:对替换类型和表达式的求值可能会产生副作用,例如实例化类模板专业化和/或函数模板专业化,生成隐式定义的函数等。此类副作用不在立即中。上下文,并可能导致程序格式错误。 —尾注]
Only invalid types and expressions in the immediate context of the function type and its template parameter types can result in a deduction failure. [ Note: The evaluation of the substituted types and expressions can result in side effects such as the instantiation of class template specializations and/or function template specializations, the generation of implicitly-defined functions, etc. Such side effects are not in the "immediate context" and can result in the program being ill-formed. — end note ]
GCC和Clang拒绝您的代码是正确的。
GCC and Clang are correct in rejecting your code.
一种解决方法是引入一个默认为顶级 T
的虚拟模板类型,并在 上使用SFINAE。像这样:
A workaround is just to introduce a dummy template type that defaults to the top-level T
, and SFINAE on that one. Like so:
template <typename T_ = T, // now the subsequent line *is* in
// an immediate context
typename = typename std::enable_if <
std::is_integral<T_>::value&& !std::is_floating_point<T_>::value
>::type>
Foo(T value1 = 50, T value2 = -50)
:value1_(value1), value2_(value2) { }
请注意, is_integral
和 is_floating_point
是互斥的,必须检查一个或另一个。
Note that is_integral
and is_floating_point
are mutually exclusive, you should only have to check one or the other.
在此示例中,将默认值移植到另一个结构中可能要简单得多,这样您可以只拥有一个类似于以下内容的构造函数:
In this example, it'd probably be a lot simpler just to farm out the default values to another struct, so that you can have just one constructor that looks like:
Foo(T value1 = FooDefaults<T>::value1, T value2 = FooDefaults<T>::value2)
: value1_(value1), value2_(value2)
{ }
这篇关于专攻模板类构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!