I'm perplexed: upon upgrading to GCC 6 (RC1) some template code using std::common_type that worked before failed. I tried on clang, and that also fails...so I must be doing something wrong!
The code amounts to:
#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();
The second common_type with three parameters of type std::type_info const & fails to compile. clang cryptically suggests I use a two-argument std::common_type, but this is in a template expansion where I can't control the inputs!
This seems very odd: why would the const type_info& case with 3 fail but not any of the other seemingly-equivalent type fail?
See here: https://godbolt.org/g/Ob4y0x
First, common_type_t<T1, T2> is (roughly) std::decay_t<decltype(true? std::declval<T1>() : std::declval<T2>())>. It decays the type - strip away referenceness, remove top-level cv-qualification, and does the array-to-pointer and function-to-pointer conversion.
So, common_type<const type_info&, const type_info&>::type is type_info. While func1's declaration appears to work, you'll have serious problems writing its definition.
common_type_t<T1, T2, T3> is common_type_t<common_type_t<T1, T2>, T3>, so common_type<const type_info&, const type_info&, const type_info&>::type is common_type<type_info, const type_info&>::type.
That results in a mixed-value-category ternary expression, which by the rules in [expr.cond] will try to make a temporary type_info out of the chosen operand - which doesn't work because type_info's copy constructor is deleted.
In SFINAE-friendly implementations, that results in common_type<const type_info&, const type_info&, const type_info&> having no member type. If you use a non-SFINAE-friendly implementation, you'll get a hard error instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With