As far as I know, you don't need to completely specialize both sides of the binary common_type
. This allows reducing the amount of specializations to 12 for one side. If you only need a common type between specializations of my_type
and my_type
, than it's sufficient to specialize on one side. Otherwise, you'd had to clone them on the right side, yielding 24 specializations.
struct my_type;
struct unique_t;
#include <type_traits>
template<class L, class R, class = void>
struct mytype_common_type
{
// not many specializations are required here,
// as you can use std::decay and don't have to use "Exact Matches"
using type = unique_t;
};
namespace std
{
template<class T> struct common_type<my_type, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type const, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type volatile, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type const volatile, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type const&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type volatile&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type const volatile&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type&&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type const&&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type volatile&&, T>
: mytype_common_type<my_type, T> {};
template<class T> struct common_type<my_type const volatile&&, T>
: mytype_common_type<my_type, T> {};
}
template<class T>
using Decay = typename std::decay<T>::type;
int main()
{
static_assert(std::is_same<unique_t,
std::common_type<my_type const volatile&&, int>::type
>{}, "!");
}