0

今日、クラスにネストされた型があるかどうかについて、型の切り替えを実行しようとしていましたreverse_iterator。これらの fora で、次のような実用的なソリューションを見つけました。

template<typename T>
struct is_reverse_iterable
{
    using yes   = uint8_t;
    using no    = uint16_t;

    template<typename U>
    static yes& test(typename U::reverse_iterator*);

    template<typename>
    static no& test(...);

    static constexpr bool value = sizeof(test<T>(0)) == sizeof(yes);
};

このクラスは、メインから条件をチェックするだけで問題なく動作しますが、その小さな関数も書いているため、問題が発生します。

template<typename T>
void foo(T&& iter)
{
    std::cout << typeid(T).name() << std::endl;
    std::cout << is_reverse_iterable<T>::value << std::endl;
}

これが私にいくつかの問題を引き起こす主なものです:

int main()
{
    using namespace std;

    vector<int> v;

    cout << typeid(decltype(v)).name() << endl;
    cout << is_reverse_iterable<decltype(v)>::value << endl;

    foo(v);

    return 0;
}

std::vector<int>ネストされた型 name が含まれているため、どこに置いても true が返さreverse_iteratorれると思うでしょう。少なくとも、私はそう思います。is_reverse_iterable<vector<int>>::valueしかし、そうではありません。上記のメインの結果は次のとおりです。

St6vectorIiSaIiEE
1
St6vectorIiSaIiEE
0

メインから呼び出された場合、構造体is_reverse_iterableは の名前reverse_iteratorを認識しましたvector<int>が、 から呼び出された場合は認識しませんでしたfoo。実際、私には理由がわかりません。誰かに問題が何であるかを説明してもらいたいです:)

PS : MinGW g++ 4.7.1 を使用してコンパイルし、オプション -std=c++11 を指定します。

4

1 に答える 1

1

問題は、 を呼び出すと、が型(左辺値参照) であるfoo(v)と推定されるため、コンパイルされないことです。自分で簡単に確認できます:Tstd::vector<int>&typename T::reverse_iterator

template<typename T>
void foo(T&& iter)
{
    std::cout << typeid(T).name() << std::endl;
    std::cout << is_reverse_iterable<T>::value << std::endl;

    typename T::reverse_iterator t;  // <-- add this line to see what's wrong
}

収量:

3.cpp: In instantiation of ‘void foo(T&&) [with T = std::vector<int>&]’:
3.cpp:40:10:   required from here
3.cpp:27:34: error: ‘std::vector<int>&’ is not a class, struct, or union type

解決策は簡単です: SFINAE を開始する前に参照を削除します。

static constexpr bool value = sizeof(test<typename std::decay<T>::type>(0))
                                == sizeof(yes);
于 2012-11-22T17:57:15.610 に答える