接受所有版本的const/volatile资格和&vs &&的类模板特化

Dav*_*one 9 c++ templates template-specialization template-meta-programming c++11

我专注std::common_type于我的类型.我定义了以下专业:

common_type<my_type, my_type>
Run Code Online (Sandbox Code Playgroud)

一切都很好.然后有人来了并打电话std::common_type<my_type, my_type &>.如果传递引用而不是引用(因为它调用std::decay类型),则默认版本的行为相同.但是,它并不遵循std::common_type我需要正确工作的非参考版本.有没有比这样做更好的方法(为了简单起见,省略了对const的rvalue-reference):

common_type<my_type, my_type>
common_type<my_type, my_type &>
common_type<my_type, my_type const &>
common_type<my_type, my_type volatile &>
common_type<my_type, my_type const volatile &>
common_type<my_type, my_type &&>
common_type<my_type, my_type volatile &&>
common_type<my_type &, my_type>
common_type<my_type const &, my_type>
common_type<my_type volatile &, my_type>
common_type<my_type const volatile &, my_type>
common_type<my_type &&, my_type>
common_type<my_type volatile &&, my_type>
common_type<my_type &, my_type &>
common_type<my_type &, my_type const &>
common_type<my_type &, my_type volatile &>
...
Run Code Online (Sandbox Code Playgroud)

当然有更好的方法吗?根据我的统计,如果我们忽略const &&和那就是49种可能的版本const volatile &&

注意:my_type实际上是一个类模板本身,所以specialize实际上看起来更像

template<intmax_t lhs_min, intmax_t lhs_max, intmax_t rhs_min, intmax_t rhs_max>
class common_type<my_type<lhs_min, lhs_max>, my_type<rhs_min, rhs_max>>
Run Code Online (Sandbox Code Playgroud)

结果在哪里 my_type<min(lhs_min, rhs_min), max(lhs_max, rhs_max)>

如果我完全控制主要模板定义,解决方案将非常简单,但我显然无法改变std::common_type.

dyp*_*dyp 2

据我所知,您不需要完全专门化二进制的两侧common_type。这允许将一侧的专业数量减少到 12 个。my_type如果您只需要和的特化之间的通用类型my_type,那么专门化一侧就足够了。否则,您必须在右侧克隆它们,从而产生 24 个专业化。

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
                  >{}, "!");
}
Run Code Online (Sandbox Code Playgroud)