高度にテンプレート化されたコードで問題が発生し、このサンプルプログラムでそれを分離しました(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タイプに対して)代わりに何を書くことができるか?