2017-06-18 5 views
13

は、次のコードを考えてみましょう:変換演算子で使用すると、コンパイラはテンプレートパラメータを推測できないのはなぜですか?

#include <utility> 

template<typename T> 
struct wrapper { 
    T value; 
}; 

struct foo { 
    operator wrapper<int>() { 
     return{10}; 
    } 
}; 


int main() { 
    foo f; 
    wrapper w = f; // error 
    std::pair p = std::make_pair(1, 0); // ok 
} 

gcc 7.1.1は、上記の標線でコンパイルに失敗します。

main.cpp: In function 'int main()': 
main.cpp:17:17: error: class template argument deduction failed: 
    wrapper w = f; // error 
       ^
main.cpp:17:17: error: no matching function for call to 'wrapper(foo&)' 
main.cpp:4:8: note: candidate: template<class T> wrapper(wrapper<T>)-> wrapper<T> 
struct wrapper { 
     ^~~~~~~ 
main.cpp:4:8: note: template argument deduction/substitution failed: 
main.cpp:17:17: note: 'foo' is not derived from 'wrapper<T>' 
    wrapper w = f; // error 
       ^

fwrapper<int>に変換可能であるので、私はそれが起こることを期待しています。そこからコンパイラはTintであると推測できるはずです。しかし、それはできません。

コンパイラは、std::pairのテンプレートパラメータを正しく推定できます。なぜ、これがwrapperの場合でないのですか?

アイデア?

+0

IMOクラステンプレートの控除で変換演算子を調べると混乱します。それが必要な場合は、明示的な控除ガイドを使用する必要があります。 – cpplearner

+0

関連:https://stackoverflow.com/q/43019240/1896169 – Justin

+0

この '演算子の構造体ラッパー()'は何ですか? 'operator wrapper'または' operator() 'を宣言していますか? – cat

答えて

11

クラステンプレート引数の控除の場合、「オーバーロードセット」は[over.match.class.deduct/1]に記述されているように構成されます。

関数と関数テンプレートのセットが形成されているあっ:それらは以下の通りである
(1.1) - テンプレートが定義されている場合、テンプレート名によって 指定されたプライマリクラステンプレートの各コンストラクタの、
(1.1.1) - テンプレートパラメータは、 クラステンプレートのテンプレートパラメータであり、コンストラクタのテンプレート のパラメータ(デフォルトのテンプレート引数を含む)が続く場合は、 (存在する場合)です。
(1.1.2) - 関数パラメータの型は、コンストラクタ のものです。
(1.1.3) - 返される型は、クラス テンプレートから取得されたテンプレートパラメータに対応するテンプレートテンプレート引数 によって指定されるクラステンプレート の特殊化です。

(1.2) - プライマリクラステンプレートCは定義されていない又は は、上記仮定のコンストラクタC(から として導出付加機能テンプレートを任意のコンストラクタを宣言していない場合)。

(1.3) - コピー控除候補と呼ばれる 仮想コンストラクタC(C)から上記のように派生した追加の関数テンプレート。

(1.4) - 各控除ガイド、 以下の特性を持つ関数または関数テンプレートの場合:
(1.4.1) - テンプレートパラメータ、もしあれば、 及び関数のパラメータはdeduction-のものですガイド。
(1.4.2) - 戻り値の型は、控除ガイドのsimple-template-idです。 1.1で

あなたが見ることができるように、マッチング「機能は、」唯一のテンプレートパラメータの型正確に引数の型と一致するようにしようとします。それはアカウントに変換を(他のほとんどのテンプレートの控除に関連した動作と同様)考慮しません。

std::pairの理由は、項目1.3と「コピー控除候補」によるものです。

関連する問題