5

は、次のコードを考えてみましょう:バリデーションリストと単一のテンプレートパラメータ:標準は何を表していますか?

#include <iostream> 
#include <type_traits> 

// Variadic version 
template<class... Variadic> 
void f(const Variadic&... variadic) 
{ 
    std::cout<<"variadic"<<std::endl; 
} 

// Single version 
template<class Single, class = typename std::enable_if<std::is_fundamental<Single>::value>::type> 
void f(const Single& single) 
{ 
    std::cout<<"single"<<std::endl; 
} 

// Main 
int main() 
{ 
    f();    // variadic 
    f(42);   // single : why? 
    f(std::string()); // variadic 
    f(42, 42);  // variadic 
    return 0; 
} 

の行は、「単一の」(G ++ 4.6.3の下で)うまくコンパイルし、オーバーロードの解決の問題が発生しないマークされ、なぜ私は理解していません。 C++ 11標準では、固定数のパラメータを持つテンプレート関数は、同じシグネチャを持つ可能性のある可変関数よりも優先されていますか?

答えて

2

'single'バージョンで2番目のenable_if、templateパラメータが使用されているため、コンパイラはそのバージョンを、有効化されているタイプで使用するより特殊なテンプレートと見なします。
variadicテンプレートをインスタンス化することができるが、 'single'はインスタンス化できないタイプがあるので、より特殊化されていると考えられます。

一般的なルールは、より特殊化されたテンプレートは、過負荷の解決であまり特殊化されていないテンプレートよりも優先されるということです。

+0

注: 'enable_if'は「シングル」過負荷がより専門的なこととは何の関係もありません、それは直交だと可能な過負荷のセットから*除去機能*であります。 –

+1

しかし、関数を削除しないと 'f (const int&)'よりも特殊な 'f (const int&)'が得られます。2番目のテンプレートパラメータが 'enable_if'であるという事実は関係ありません。実際には2番目のパラメータがあることが関係しており、過負荷が選択される理由です。 'enable_if'型を' void'に置き換えると、 'f(std :: string())'のためにそのオーバーロードが実行可能になります。 @MatthieuM。 –

+0

。私はそれが 'enable_if'を使用する意図であることに同意します。 Jonathanが説明しているように、テンプレートの副作用は、削除されていないケースに対してテンプレートをより特殊化することです。 –

5

It is reallyquite simple(2生例、gccと打ち鳴らす)

template<class...T> void foo(T&&...) {std::cout << "...T\n";} 
template<class T> void foo(T&&) {std::cout << "T\n";} 
int main() { 
    foo(3); 
} 

オーバーロードが...を取っていない選択は、明示的なテンプレートパラメータである場合に好ましいように見えます。

class=std::enable_if_tはこれを変更しません。

したがって、両方の関数fが候補である場合、コンパイラは、変数を持たないコンパイラを優先します。 [temp.deduct.partial]

/8半順序時にテンプレート引数を推測

14.8.2.4:

Aは、関数パラメータパックとPから転換した場合には、パラメータパックではありません、型控除が失敗します。それ以外の場合は、結果のタイプPAを使用して、控除が14.8.2.5に記載されているように行われます。 P関数パラメータパックである場合、引数テンプレートの残りの各パラメータの型のタイプAは、関数パラメータパックの宣言-ID の型Pと比較されます。各比較では、関数パラメータパックで展開されたテンプレートパラメータパックの後続の位置のテンプレート引数が導出されます。指定された型の控除が成功した場合、引数テンプレートの型は、少なくともパラメータテンプレートの型と同じように特殊化されているとみなされます。 [ 例:特に

template<class... Args> void f(Args... args); // #1 
template<class T1, class... Args> void f(T1 a1, Args... args); // #2 
template<class T1, class T2> void f(T1 a1, T2 a2); // #3 
f(); // calls #1 
f(1, 2, 3); // calls #2 
f(1, 2); // calls #3; non-variadic template #3 is more 
// specialized than the variadic templates #1 and # 

f(1,2)例。

std::stringTに渡すと、すべてのenable_if_t句は考慮事項から1つの引数のバージョンを削除します。

関連する問題