0

今天,我试图对某个类是否具有嵌套类型进行类型切换reverse_iterator。我在这些论坛上找到了一些可行的解决方案,如下所示:

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);
};

如果我只是从 main 中检查条件,这个类就可以正常工作,但是,我还编写了那个小函数,这会导致一些问题。

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 reverse_iterator,人们会认为 - 或者至少,我认为 -is_reverse_iterable<vector<int>>::value无论我放在哪里都会返回 true。但事实并非如此。这是上面主要的结果:

St6vectorIiSaIiEE
1
St6vectorIiSaIiEE
0

当从 main 调用时,结构is_reverse_iterable识别 中的名称reverse_iteratorvector<int>但从 调用时它没有这样做foo。实际上,我不知道为什么,我希望有人向我解释问题所在:)

PS:我使用 MinGW g++ 4.7.1 编译,选项 -std=c++11。

4

1 回答 1

1

问题是当你调用时foo(v),它被推断T为类型std::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 回答