3

次のサンプルコードがあります。

class Serializable {};

class MyData : public Serializable {};

void GetData( Serializable& ) {}

template<typename T>
void GetData( T& data )
{
    std::istringstream s{"test"};
    s >> data;
}

int main()
{
    MyData d;
    GetData(d);
}

(ライブサンプル)

オーバーロード解決規則に基づいて、基本クラスの型が であるため、非テンプレート バージョンを優先する必要がありSerializableます。ただし、オーバーロード解決のためにテンプレート バージョンをインスタンス化するときにエラーが発生すると、SFINAE が起動することを期待しています (型に対して >> 演算子が定義されていない場合は考慮されないため)。

テンプレートが使用されないのに、まだ失敗するのはなぜですか?

4

1 に答える 1

5

オーバーロード解決規則に基づいて、基本クラスの型が であるため、非テンプレート バージョンを優先する必要がありSerializableます。

そうではありません。[over.match.best]:

これらの定義が与えられた場合、実行可能な関数は、すべての引数 i について、ICSi(F1) が ICSi(F2) よりも悪い変換シーケンスではない場合、F1別の実行可能な関数よりも優れた関数であると定義されます。F2

  • いくつかの引数 j に対して、ICSj(F1) は ICSj(F2) よりも優れた変換シーケンスです。そうでない場合は、
  • […]
  • F1関数テンプレートの特化ではなく、関数テンプレートの特化F2です […]

これは、関数テンプレートの推測された特殊化が、通常の関数が必要とする変換よりも良くない変換を必要とする場合にのみ、ルールが適用されることを意味します。また、dtoSerializable&のバインディングは、d の to MyData&(特殊化のパラメーターの型) [over.ics.ref]のバインディングよりも悪い変換です。

参照型のパラメーターが引数式に直接 (8.5.3) バインドされる場合、引数式がパラメーター型の派生クラスである型を持たない限り、暗黙的な変換シーケンスは恒等変換です。シーケンスは、派生から塩基への変換 (13.3.3.1) です。

ただし、オーバーロード解決のためにテンプレート バージョンをインスタンス化するときにエラーが発生すると、SFINAE が起動することを期待しています (型に対して >> 演算子が定義されていない場合は考慮されないため)。

SFINAE は、関数テンプレートのコンテンツには適用されません。[一時控除]/8:

関数の型とそのテンプレート パラメーターの型の直接のコンテキストで無効な型と式のみが推定エラーになる可能性があります。

したがって、関数テンプレートの推定特殊化が実際に選択され、その定義のインスタンス化中にコンパイラ エラーが発生します。

于 2014-12-04T18:35:46.217 に答える