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
Ответы
Ответ 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, вы получите жесткую ошибку.