2

このコードは、clang++ 6.0 または g++4.9.1 ではコンパイルされません (コードに意味はありませんが、これが発生する最小の例です)。

#include <forward_list>

template<typename T>
T getItem(typename std::forward_list<T>::const_iterator it) {
    return *it;
}

template<typename T>
void foo() {
    std::forward_list<T> list;
    auto item = getItem(list.cbegin());
}

template<typename T>
void bar(const std::forward_list<T>& list) {
    auto item = getItem(list.cbegin());
}

int main() {
    std::forward_list<int> list;
    bar(list);
}

このエラーが発生します

t2.cpp:17:17: error: no matching function for call to 'getItem'
    auto item = getItem(list.cbegin());
                ^~~~~~~
t2.cpp:22:5: note: in instantiation of function template specialization 'bar<int>' requested here
    bar(list);
    ^
t2.cpp:4:3: note: candidate template ignored: couldn't infer template argument 'T'
T getItem(typename std::forward_list<T>::const_iterator it) {
  ^
1 error generated.

それを修正するには、bar()の呼び出しを次のように変更する必要があります。

template<typename T>
void bar(const std::forward_list<T>& list) {
    auto item = getItem<T>(list.cbegin());
}

コンパイラがテンプレート引数を推測できない理由がわかりません。奇妙なことに、コンパイラは完全に満足していfoo()ます。

4

1 に答える 1

8

推定されていないコンテキストからテンプレート引数を推定しようとしています、§ [temp.deduct.type]/5

非推定コンテキストは次のとおりです。

— 修飾 ID を使用して指定されたタイプのネストされた名前指定子。

すなわち

template<typename T>
T getItem(typename std::forward_list<T>::const_iterator it)
                   ^^^^^^^^^^^^^^^^^^^^

§ [temp.deduct.type]/ 4

ただし、特定のコンテキストでは、値は型推定に参加せず、代わりに別の場所で推定された、または明示的に指定されたテンプレート引数の値を使用します。テンプレート パラメーターが推定されないコンテキストでのみ使用され、明示的に指定されていない場合、テンプレート引数の推定は失敗します。

インスタンス化しようとするfoo と、同じエラーが発生しますfoo従属名はインスタンス化時にのみ検索されるため、上記のコードではエラーは発生しません(これは一般に2 フェーズ検索と呼ばれます)。Cfr. インスタンス化されていない C++ テンプレート関数のセマンティック コレクトネス

于 2014-11-10T11:34:43.513 に答える