Talk:cpp/types/common type
From cppreference.com
For some reason it is impossible to make
std::common_type<std::unique_ptr<int> & , std::unique_ptr<int> >::type
Wouldn't it be better to implement std::common_type like this:
Run this code
#include <memory> #include <type_traits> namespace MyStd { template <class ...T> struct common_type; template <class T> struct common_type<T> { typedef std::decay_t<T> type; }; template <class T, class U> struct common_type<T, U> { typedef std::decay_t<decltype(true ? std::declval<std::decay_t<T>>() : std::declval<std::decay_t<U>>() )> type; }; } int main() { //this will fail: //std::common_type_t< std::unique_ptr<int>& , std::unique_ptr<int> > failtest; MyStd::common_type<std::unique_ptr<int> & , std::unique_ptr<int> >::type tt = std::make_unique<int>(33); static_assert(std::is_same<MyStd::common_type<int, double>::type, double>(), "pass"); static_assert(std::is_same<MyStd::common_type<int, double&>::type, double>(), "pass"); static_assert(std::is_same<MyStd::common_type<int, double&&>::type, double>(), "pass"); static_assert(std::is_same<MyStd::common_type<int&, int>::type, int>(), "pass"); static_assert(std::is_same<MyStd::common_type<std::unique_ptr<int> & , std::unique_ptr<int> >::type, std::unique_ptr<int>>(), "pass"); static_assert(std::is_same<MyStd::common_type<int, int&>::type, std::common_type<int&, int&>::type>(), "pass"); }
--Shchvova (talk) 17:20, 24 February 2015 (PST)
- C++ is way ahead of you! C++14 specified common_type in terms of decay_t<decltype(true ? declval<T>() : declval<U>())>, but the current C++17 draft already states that the two args of the conditional operator are xvalues. This was part of LWG 2408 that wasn't yet reflected on this cppreference page. Since it's classified as a defect in C++14, I believe you are justified to file bug reports against compilers (technically, against library implementations) --Cubbi (talk) 19:21, 24 February 2015 (PST)
[edit] Incorrect note
It is stated under Notes, "For arithmetic types, the common type may be viewed as the type of the (possibly mixed-mode) arithmetic expression such as T0() + T1() + ... + Tn()." This is incorrect when the types are all the same and ranked lower than int.
decltype(char{} + char{}) is int, but common_type_t<char, char> is char (because of course decltype(true ? char{} : char{}) is char), as demonstrated below:
Run this code
#include <type_traits> template <typename... Ts> struct print_types; int main() { print_types< std::common_type_t<char, char>, decltype(true ? char{} : char{}), decltype(char{} + char{}) >{}; }