Namespaces
Variants
Views
Actions

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:

#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:

#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{})
    >{};
}

--Oktal (talk) 10:55, 12 March 2015 (PDT)

Good point! The note may have to be turned around to say that it *can't* be used to indicate the result of a mixed-type arithmetic expression. --Cubbi (talk) 11:10, 12 March 2015 (PDT)