嵌套成员类型识别

Nested member type recognition

本文关键字:识别 类型 成员类 成员 嵌套      更新时间:2023-10-16

今天,我试图对某个类是否具有嵌套类型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>包含嵌套类型名称reverse_iterator,人们会认为 - 或者至少,我会认为 - 无论我在哪里放置它,is_reverse_iterable<vector<int>>::value都会返回true。但事实并非如此。这是上述主要内容的结果:

St6vectorIiSaIiEE
1
St6vectorIiSaIiEE
0

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

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

问题是当你调用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);