专用于模板类构造函数
specialize a template class constructor
我想专门化一个模板类构造函数:
如果类型为 int,则默认值为 50 和 -50,如果是浮点数,则默认值应为 0.5 和 -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_;
}
它在Visual Studio 2013中工作得很好。
但是 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错误?!
您的代码不正确。顶级T
不能在 SFINAE 上下文中用于其方法,而这正是您尝试执行的操作。只有在直接情况下发生的替换才可能导致扣除失败(§14.8.2/8):
只有函数类型及其模板参数类型的直接上下文中的无效类型和表达式才可能导致推导失败。[ 注意:对替换类型和表达式的计算可能会导致副作用,例如类模板专用化和/或函数模板专用化的实例化、隐式定义函数的生成等。这种副作用不在"直接上下文"中,可能导致程序格式不正确。— 尾注 ]
GCC 和 Clang 拒绝您的代码是正确的。
解决方法是引入默认为顶级T
的虚拟模板类型,以及该模板上的 SFINAE。这样:
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
是互斥的,您只需检查其中一个。
在此示例中,将默认值外包给另一个结构可能会简单得多,这样您就可以只有一个如下所示的构造函数:
Foo(T value1 = FooDefaults<T>::value1, T value2 = FooDefaults<T>::value2)
: value1_(value1), value2_(value2)
{ }
相关文章:
- 没有用于初始化C++中的变量模板的匹配构造函数
- 用于创建命名构造函数的宏
- 没有用于调用默认构造函数的匹配函数
- std::vector 是否有用于引用的复制构造函数?
- 没有用于初始化模拟工厂的匹配构造函数
- 模板 ctor 类型推导不起作用(没有匹配的构造函数用于初始化 ...)与函数<>参数
- 没有适用于 std::unique_ptr 的适当默认构造函数
- 具有字符串文本构造函数的类不适用于 const 引用初始化
- 用于赋值的参数化构造函数
- C++构造函数,一个用于度,一个用于弧度
- 用于 protobuf 转换的大括号初始化样式构造函数
- 使用构造函数作为成员函数的 C++(用于序列化)
- 构造函数不能用于启发性化
- 错误:没有用于初始化和mexfunction的匹配构造函数
- 没有用于初始化可变参数模板类的匹配构造函数
- ifstream 没有用于初始化的匹配构造函数
- 将 SFINAE 用于模板化构造函数时出现问题
- 在已发布的结构中添加构造函数(用于 memcpy)是否安全?
- 没有匹配的构造函数用于初始化模板化类的构造函数
- “没有匹配的构造函数用于初始化”与矢量