クラステンプレートの特殊化を優先させるルールは、特殊化を関数テンプレートに書き直し、関数テンプレートの順序付けルール[temp.class.order] 。そして、この例を考えてみましょう:クラステンプレートの特殊な部分順序付けと関数の合成
#include <iostream>
template <class T> struct voider { using type = void; };
template <class T> using void_t = typename voider<T>::type;
template <class T, class U> struct A { };
template <class T> int foo(A<T, void_t<T>>) { return 1; }
template <class T> int foo(A<T*, void>) { return 2; }
int main() {
std::cout << foo(A<int*, void>{});
}
ここでどちらもgccと打ち鳴らす印刷2
。前の例では意味がありますが、推測されていないコンテキスト(void
:void_t<T>
)に対する推測は無視されます。したがって、<T, void_t<T>>
を<X*, void>
に対して控除しますが、<T*, void>
を<Y, void_t<Y>>
に対して控除すると両方の引数で失敗します。ファイン。 1
と2
の間、あいまいなよう
#include <iostream>
template <class T> struct voider { using type = void; };
template <class T> using void_t = typename voider<T>::type;
template <int I> struct int_ { static constexpr int value = I; };
template <class T, class U> struct A : int_<0> { };
template <class T> struct A<T, void_t<T>> : int_<1> { };
template <class T> struct A<T*, void> : int_<2> { };
int main() {
std::cout << A<int*, void>::value << '\n';
}
打ち鳴らすとgccレポートの両方この専門分野:
は今、この一般化を検討してください。しかし、なぜ?合成された関数テンプレートはあいまいではありません。これらの2つのケースの違いは何ですか?
ページング@bogdan。 – Barry
私は専門家ではありませんが、私はそれが 'void'と' void_t'の両方に特化していると思います。これは[作品](http://ideone.com/91pVA5) – xinaiz
@BlackMosesそれは、部分的な注文はしません。一致する特殊化が1つだけある場合は、それがちょうど選択されました – Barry