Подтвердить что ты не робот

Std:: common_type со ссылками на type_info

Я озадачен: при обновлении до GCC 6 (RC1) некоторый код шаблона с использованием std::common_type, который работал до отказа. Я пробовал на clang, и это также терпит неудачу... поэтому я должен делать что-то неправильно!

Код составляет:

#include <type_traits>
#include <typeinfo>

using namespace std;

// common_type of two const type_info& is ok (compiles ok)
common_type<const type_info&, const type_info&>::type func1();

// common_type of three type_info& is bad...(fails to compile)
common_type<const type_info&, const type_info&, const type_info&>::type func2();

// common_type of two const int& is ok
common_type<const int&, const int&>::type func3();

// common_type of three const int& is ok too!
common_type<const int&, const int&, const int&>::type func4();

Второй common_type с тремя параметрами типа std::type_info const & не скомпилируется. clang cryptically предлагает использовать два аргумента std::common_type, но это в расширении шаблона, где я не могу управлять входами!

Это кажется очень странным: почему сбой const type_info& с ошибкой 3, но не какой-либо другой, казалось бы, эквивалентный тип не работает?

Смотрите здесь: https://godbolt.org/g/Ob4y0x

4b9b3361

Ответ 1

Во-первых, common_type_t<T1, T2> (примерно) std::decay_t<decltype(true? std::declval<T1>() : std::declval<T2>())>. Он разлагает тип - отбрасывает референцию, удаляет квалификацию cv верхнего уровня и преобразует массив в указатель и преобразование функции в указатель.

Итак, common_type<const type_info&, const type_info&>::type - type_info. Хотя объявление func1, похоже, работает, у вас возникнут серьезные проблемы с написанием его определения.

common_type_t<T1, T2, T3> common_type_t<common_type_t<T1, T2>, T3>, поэтому common_type<const type_info&, const type_info&, const type_info&>::type - common_type<type_info, const type_info&>::type.

Это приводит к тройному выражению категории со смешанной стоимостью, которое по правилам в [expr.cond] попытается сделать временный type_info из выбранного операнда - который не работает, потому что type_info copy конструктор удален.

В SFINAE-дружественных реализациях, в результате чего common_type<const type_info&, const type_info&, const type_info&> не имеет члена type. Если вы используете реализацию, отличную от SFINAE, вы получите жесткую ошибку.