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