简体   繁体   中英

std::common_type with references to type_info

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM