Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 类模板专门化,接受const/volatile限定和&;vs&&;_C++_Templates_C++11_Template Specialization_Template Meta Programming - Fatal编程技术网

C++ 类模板专门化,接受const/volatile限定和&;vs&&;

C++ 类模板专门化,接受const/volatile限定和&;vs&&;,c++,templates,c++11,template-specialization,template-meta-programming,C++,Templates,C++11,Template Specialization,Template Meta Programming,我专门为我的类型std::common_type。我定义了以下专业化: common_type<my_type, my_type> 肯定有更好的办法吗?据我统计,如果我们忽略const&和const volatile&& 注意:my_类型实际上是一个类模板本身,因此specialize看起来更像 template<intmax_t lhs_min, intmax_t lhs_max, intmax_t rhs_min, intmax_t rhs_max> class c

我专门为我的类型
std::common_type
。我定义了以下专业化:

common_type<my_type, my_type>
肯定有更好的办法吗?据我统计,如果我们忽略
const&
const volatile&&

注意:my_类型实际上是一个类模板本身,因此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>>
模板
类公共类型
其中结果为
my\u type


如果我能够完全控制主模板定义,那么解决方案将非常简单,但我显然无法更改
std::common_type

我建议编写没有cv-和ref-限定符的专门化, 并在
std::common_type
周围使用包装器,如下所示:

template <typename T>
using decay_t = typename std::decay<T>::type;

/* Our wrapper which passes decayed types to std::common_type<>. */
template <typename... T>
using CommonType = std::common_type<decay_t<T>...>;

namespace std {

  /* Specialization for my_type<>. */
  template <intmax_t lhs_min, intmax_t lhs_max,
            intmax_t rhs_min, intmax_t rhs_max>
  struct common_type<my_type<lhs_min, lhs_max>,
                     my_type<rhs_min, rhs_max>> {
    using type = /* ... */;
  };

}  // std
template <typename Lhs, typename Rhs>
using common_type_impl_t = 
    decay_t<decltype(true ? std::declval<Lhs>() : std::declval<Rhs>())>;
很好用

我很困惑专业化是如何被使用的,直到我意识到它不是。
std::common_type
的一般实现在if-else表达式上使用
decltype()
,如下所示:

template <typename T>
using decay_t = typename std::decay<T>::type;

/* Our wrapper which passes decayed types to std::common_type<>. */
template <typename... T>
using CommonType = std::common_type<decay_t<T>...>;

namespace std {

  /* Specialization for my_type<>. */
  template <intmax_t lhs_min, intmax_t lhs_max,
            intmax_t rhs_min, intmax_t rhs_max>
  struct common_type<my_type<lhs_min, lhs_max>,
                     my_type<rhs_min, rhs_max>> {
    using type = /* ... */;
  };

}  // std
template <typename Lhs, typename Rhs>
using common_type_impl_t = 
    decay_t<decltype(true ? std::declval<Lhs>() : std::declval<Rhs>())>;
过去了。现在,把
volatile
扔进去,它就会像@Vincent指出的那样崩溃,这进一步证明了没有使用专门化

因此,我的结论是,两种情况中的一种会发生:

  • 标准实现将发生变化,这样即使存在cv-和ref-限定符,也会使用专门化,在这种情况下,您可以丢弃
    CommonType
    包装器,这很简单,而且您只定义了一个专门化
  • 标准实现没有改变,但您仍然只定义了一个专门化,并使用
    CommonType

据我所知,您不需要完全专门化二进制
通用类型的两侧。这允许将一方的专门化数量减少到12个。如果在
my\u type
my\u 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
                  >{}, "!");
}
struct my_type;
结构唯一性;
#包括
模板
结构mytype\u公共类型
{
//这里需要的专业不多,
//因为您可以使用std::decay,而不必使用“精确匹配”
使用类型=唯一\u t;
};
名称空间标准
{
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
模板结构公共类型
:mytype_common_type{};
}
模板
使用Decay=typename std::Decay::type;
int main()
{
静态断言(std::is_same{},“!”);
}

std::common_type
的标准库实现有哪些功能?这里的实现没有多少自由度。它必须调用
std::decay
(或者有一个无法区分的实现)。毫无疑问,gcc 4.8.2就是这么做的,只是为了确保:您不能使用与
std::common_type
不同的东西,即更改“呼叫站点”?您不能定义受SFINAE保护的转换运算符模板来“自然”执行
my_type
?我可以强制所有用户在调用站点使用特殊的
common_type
,但我正在尝试编写通用库。我不能指望我的所有用户(以及他们可能使用的所有库)总体上都使用我的特殊
common_type
:这违背了泛型代码的目的。我不能定义转换运算符/隐式构造函数来完成这项工作,因为C++假设您想将其中一种类型转换为另一种类型。我的两个类的公共类型通常是第三种类型,不能由
操作符处理:
。我认为您至少可以通过使用部分专门化而不是显式(完全)专门化,将问题减少到二进制
公共类型
一侧的所有cv限定引用类型,类似于
模板公共类型
然后检查删除引用后,
T
是否是
myu类型的专门化(通过继承重定向)。我猜
chrono
之所以有效,是因为
duration
s的隐式转换,而不是因为
common\u类型的专门化。当然,这对OP不起作用(结果类型可能是第三种类型)。
volatile
的东西不起作用,因为转换需要一个
常量&
,而不是
常量volatile&
。实际上,我不知道如何在右侧复制它。如果我定义
std::common_type
std::common_type
,这不会导致不明确的专门化吗?@DavidStone你是对的,如果你只是使用专门化
common_type
common_type
,那将是不明确的。但是,您可以通过对右侧的专门化使用
enable\u if
来修复此问题:
template struct common\u type:mytype\u common\u type{}
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
                  >{}, "!");
}