SFINAEで実験していました。 my_function
のインスタンシエーションでmy_type_a
を推測できないのはなぜですか?SFINAEとテンプレート関数のインスタンス化:SFINAE対応型の関数引数でテンプレート引数を使用できないのはなぜですか?
class my_type_a {};
template <typename T>
class my_common_type {
public:
constexpr static const bool valid = false;
};
template <>
class my_common_type<my_type_a> {
public:
constexpr static const bool valid = true;
using type = my_type_a;
};
template <typename T> using my_common_type_t = typename my_common_type<T>::type;
template <typename T, typename V>
void my_function(my_common_type_t<T> my_cvalue, V my_value) {}
int main(void) {
my_function(my_type_a(), 1.0);
}
G ++は私にこれを与える:私が期待したもの
/home/flisboac/test-template-template-arg-subst.cpp: In function ‘int main()’:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: error: no matching function for call to ‘my_function(my_type_a, double)’
my_function(my_type_a(), 1.0);
^
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: candidate: template<class T, class V> void my_function(my_common_type_t<T>, V)
void my_function(my_common_type_t<T> my_type, V my_value) {}
^~~~~~~~~~~
/home/flisboac/test-template-template-arg-subst.cpp:18:6: note: template argument deduction/substitution failed:
/home/flisboac/test-template-template-arg-subst.cpp:21:30: note: couldn't deduce template parameter ‘T’
my_function(my_type_a(), 1.0);
^
は、私がmain
で行ったようにmy_function
を呼び出すときに、T
は、関数の最初の引数の型、およびその型に推測されるだろう、ということでした関数のインスタンス化で使用されます。しかし、
my_common_type_t<T>
が機能する前にインスタンス化され、それでも、
my_cvalue
の種類がとにかく
my_type_a
になるだろうので、これは動作しないでしょう、なぜ私が見ることができないようですか?私はちょうど2つ(またはそれ以上)のレベルのテンプレート間接参照を避けるべきですか?
'my_common_type :: type'では、' T'は[推論されないコンテキスト](http://en.cppreference.com/w/cpp/language/template_argument_deduction#Non-deduced_contexts)にあります。あなたは 'my_common_type'を' my_type_a'と互換性があるように出てくることを期待して、 'my_common_type'を可能なすべての型' T'でインスタンス化することを期待しています。そのようなタイプを分析的に見つけようと試みる定理を証明する定理に従事している。コンパイラはどちらも実行しません。 –
@Igor私は、あなたが提供したリンクからのルール1が私の例と必ず一致することを理解しています。しかし、なぜTが必ずしも 'my_type_a 'ではないのはなぜ分かりませんか? 'my_common_type'が 'my_function'をインスタンス化する前にインスタンス化されていれば、型は' my_type_a'または何もない(したがって、関数はSFINAEを通して削除されます)。コンパイラは、その間またはその後にインスタンス化された場合、コンパイラは 'my_common_type 'の情報を候補として持つでしょう(そのため、 'T = my_type_a')、そうではありませんか? –
*「なぜわかりませんか」*これは私が話していた定理を証明する運動です。ここで「クリア」とは、「利用可能な事実から証明できる」ことを意味します。おそらくそれは可能ですが、コンパイラはこの種の推論エンジンを持つ必要はありません。 –