2016-12-01 4 views
2
#include <iostream> 
#include <type_traits> 

using namespace std; 

template<typename T> 
constexpr auto is_pure_input_iterator(int) -> 
conditional_t 
< 
    is_convertible_v 
    < 
    iterator_traits<T>::iterator_category, 
    input_iterator_tag 
    >, 
    true_type, false_type 
>; 

template<typename> 
constexpr false_type is_pure_input_iterator(...); 

int main() 
{ 
    cout << boolalpha 
     << decltype(is_pure_input_iterator<istream_iterator<int>>(0))::value 
     << endl; 

    return {}; 
} 

予想される出力は、trueである必要がありますが、実際の出力はfalseです。この例では、SFINAEが期待どおりに機能しないのはなぜですか?

私のコードで何が間違っていますか?

+1

'typename iterator_traits :: iterator_category'にする必要があります。それ以外の場合、このC++ 14-edバージョンhttp://coliru.stacked-crooked.com/a/461c077a5cb8fcbcはうまく動作します。出力は 'true'です。 – AnT

+2

また、true_typeが2回繰り返されるのは誤字のようです。 – Eugene

+1

なぜこの単純なコード 'std :: is_convertible :: iterator_category、std :: input_iterator_tag>'を使わないのですか?あなたがtypenameを忘れたときに警告を出します – Danh

答えて

1

typenameがありません。

typenameの欠如は、あなたがTを代用する場合

template<typename T> 
constexpr auto is_pure_input_iterator(int) -> 
conditional_t 
< 
    is_convertible_v 
    < 
    iterator_traits<T>::iterator_category, 
    input_iterator_tag 
    >, 
    true_type, false_type 
>; 

は失敗します。デフォルトでは、iterator_traits<T>::iterator_categoryが値であると仮定されます。あなたの具体的なTについては、これはタイプです(これはすべてTに当てはまります)。これはあなたのコンパイラによる置換エラーとして扱われているようです(あなたのコンパイラが正しいかどうかは不明です))。

is_pure_input_iteratorが置換エラーによって除外されると、もう1つのオーバーロードが選択されます。これはfalse_typeです。

iterator_traits<T>::iterator_categoryの前にtypenameを追加すると、@ AnT2は、hereと表示されます。 is_convertible_vとして


最初の引数としてタイプを必要とし、関係なく、Titerator_traits<T>::iterator_categoryの唯一の値にすることができ、あなたのis_pure_input_iteratorは証明可能それがこの障害を持っていないような何のTを持つことはできません。これを検出して診断プログラム(コンパイラが発行しない)を生成する規則があるか、またはプログラムが不正なため診断不要です。

関連する問題