2

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

4

1 に答える 1

3

最初の質問へ、エラー メッセージについて:

のコンストラクターは、初期化子リストのコンストラクターOPTION==2とは見なされません。そのようなコンストラクターは、単一の パラメーター (またはそのような参照) を持つ必要があるか、他のすべてのパラメーターに既定の引数が必要なためです。(8.5.4 リストの初期化 [dcl.init.list] #2)。std::initializer_list<E>

したがって、初期化子リストのコンストラクターが見つからない場合、コンパイラーは、初期化子リストの要素で構成される引数リストを使用して他のコンストラクターを試行し、明示的なコンストラクターを見つけます。また、暗黙的な変換のコンテキストにいるため (代入演算子のパラメーターの初期化) )、エラー メッセージで失敗します。

于 2012-12-07T14:13:04.647 に答える