我在一个高度模板化的代码中遇到了问题,我在这个示例程序中分离了它(我用g ++ 4.7.1编译):
#include <iostream>
#include <initializer_list>
#include <type_traits>
#define OPTION 2
// Test class
template<typename T = double>
class MyClass
{
public:
// Constructors
MyClass(const MyClass<T>& source)
{std::cout<<"copy constructor"<<std::endl;}
#if OPTION == 1
template<typename T2 = T>
MyClass(const std::initializer_list<T2>& source)
{std::cout<<"init constructor"<<std::endl;} // OPTION 1
#elif OPTION == 2
template<typename T2 = T, class... Misc>
MyClass(const std::initializer_list<T2>& source, const Misc&... misc)
{std::cout<<"init+misc constructor"<<std::endl;} // OPTION 2
#endif
template<class... Misc>
explicit MyClass(const Misc&... misc)
{std::cout<<"misc constructor"<<std::endl;}
// Assignment
inline MyClass<T>& operator=(const MyClass<T>& rhs)
{std::cout<<"copy assignment"<<std::endl; return *this;}
template<class Misc>
inline MyClass<T>& operator=(const Misc& rhs)
{std::cout<<"misc assignment"<<std::endl; return *this;}
};
// Main
int main(int argc, char* argv[])
{
MyClass<double> x;
x = {4., 8., 15., 16., 23., 42.}; // CALL LINE
return 0;
}
问题如下。使用OPTION == 1
,一切正常,CALL LINE
调用“init构造函数”。
但是对于OPTION == 2
,我有以下错误消息:
error: converting to ‘const MyClass<double>’ from initializer list would use
explicit constructor ‘MyClass<T>::MyClass(const Misc& ...) [with Misc = {double,
double, double, double, double, double}; T = double]’
问题是:为什么?它是正常的还是g ++的错误?
此外,我需要一个解决方法:我必须实现没有选项1的选项2构造函数。对我来说最明显的事情是使用enable来阻止对显式构造函数的调用,如:
template<class... Misc, class std::enable_if<SOMETHING>::type>
explicit MyClass(const Misc&... misc)
{std::cout<<"misc constructor"<<std::endl;}
我的问题是:我可以编写什么而不是SOMETHING
来阻止每个std::initializer_list<T2>
(对于所有T2类型)?
答案 0 :(得分:3)
关于第一个问题,关于错误信息:
OPTION==2
中的构造函数不被视为初始化列表构造函数,因为这样的构造函数需要具有单个std::initializer_list<E>
参数(或此类引用)或所有其他参数应具有默认参数。 (8.5.4列表初始化[dcl.init.list]#2)。
因此,没有找到初始化列表构造函数,编译器尝试其他构造函数,其参数列表由初始化列表的元素组成,找到显式构造函数,因为我们在上下文中隐式转换(初始化赋值运算符的参数)失败并显示错误消息。