Распознавание типов вложенных элементов

Сегодня я пытался выполнить переключение типов, если какой-то класс имеет вложенный тип 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);
};

Этот класс работает просто отлично, если я просто проверяю условие из основного, однако я также написал эту маленькую функцию, которая вызывает некоторые проблемы.

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 вернул бы истину, куда бы я ни положил. Но это не так. Вот результат основного выше:

St6vectorIiSaIiEE
1
St6vectorIiSaIiEE
0

Когда вызывается из основного, структура is_reverse_iterable узнал имя reverse_iterator в vector<int>, но он не сделал этого при вызове из foo, На самом деле, я понятия не имею, почему, и я хотел бы, чтобы кто-нибудь объяснил мне, в чем проблема 🙂

Постскриптум : Я использую MinGW g ++ 4.7.1 для компиляции с опцией -std = c ++ 11.

0

Решение

Проблема в том, что когда вы звоните foo(v), выводится, что T имеет тип std::vector<int>& (lvalue-ссылка), так 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);
1

Другие решения

Других решений пока нет …

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector