2017-07-14 10 views
1

SFINAEを新しくしました。私は気付いた:SFINAEでのテンプレート減算

template <typename T> void f(T t) { t.Crash(); } // version 1 
void f(...) { } // The sink. 
f(1); 

template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2 
void f(...) { } // The sink. 
f(1); 

バージョン2では、SFINAEのため、エラーをスローして楕円シンクを選択しません。なぜバージョン1では、コンパイラが停止して不平を言うのですか?

SFINAEは身体ではなく署名にのみ適用されますか?バージョン1ではテンプレート関数を優先しますが、どの段階でコンパイラが停止してエラーをスローしますか?

テンプレートオーバーロードの解消に関しては、コンパイラの処理段階を明示的に説明してください。

答えて

4

しかし、なぜバージョン1では、コンパイラは停止して文句を言うのですか? Tがコールf(1)からintと推測することができるので、

template <typename T> void f(T t) { t.Crash(); } // version 1 
void f(...) { } // The sink. 
f(1); 

は、上記fのテンプレートバージョンではそこには代替の失敗がありません。コンパイラはintとしてTを推定した後itの種類を推測する必要があります、ので、過負荷解決規則に従って、f<int>(int)は、より、f(...)


template <typename T> void f(const T& t, typename T::iterator* it = nullptr) { } // version 2 
void f(...) { } // The sink. 
f(1); 

が置換障害がありますよりも好まれます。これは無効なint::iteratorの代わりにintに置き換えられます。機能上の


SFINAEは、有効な関数テンプレートの特殊を作成するのコンテキストで動作します。

SFINAEは身体ではなく署名にのみ適用されますか?

あなたはそのような何かを言うことができます...これらの有効なコード例で戦利品を取る:

一方
//Just the declaration 
template <typename T> 
void f(T t); 

void f(...); 

int main(){ 
    f(1); //selects f<int>(int) 
} 

//just the declarations. 
template <typename T> 
void f(const T& t, typename T::iterator* it = nullptr); 

void f(...); 

int main(){ 
    f(1); //selects f(...) 
}