27

in 中的某些类型转换<type_traits>也可以使用核心语言语法来表达(例如std::add_const<T>::typeis/seems 等价于const T)。Dtto for std::add_lvalue_reference,也许还有其他人。这些类型特征有什么用?

我完全理解标准将提供一个没有它们的“不完整工具箱”,我可以想象以元方式使用,如下所示:

template<typename In, template <typename> class Modifier>
struct Apply {
  typedef typename Modifier<T>::type Out;
};

Apply<int, std::add_const>

这些特征是否还有其他用例可以用句法表达,或者它们只是“出于完整性感”而包含在偶尔的元使用中?

4

4 回答 4

23

这些特征来自 Boost 以及将它们添加到标准N1345的提议,引用 Andrei Alexandrescu 的话说:

add_const“我理解添加、add_volatileadd_cv和的对称性论点add_pointer,但我主张消除它们。语言提供的等价物更简单、更好。”

同样的提议也给出了这个理由:

作者注:从表面上看,add_const、add_volatile 和 add_cv 类是无关紧要的,例如,对于所有 T,add_const::type 与 T const 相同(目前这不适用于函数类型 - 但issue 295解决这个问题)。然而,boost 的经验是,一些用户要求这些模板存在于库中,原因如下: (a) 一些用户发现这些模板更明确 - 特别是在组合转换模板时,用户喜欢“内置这些模板提供的文档”。(b) 并非所有用户都知道允许对引用进行 cv 限定且无效,或者允许对已经 cv 限定的类型进行 cv 限定但无效。(c) 当 cv 限定作为引用的类型或已经具有 cv 限定符时,编译器可能会发出警告,可以实现这些模板,以便在这些情况下抑制这些消息。

此外,对于add_referenceadd_lvalue_reference在标准中重命名为):

作者注:add_reference 模板是 boost 类型特征库背后的原始动机之一。然而,问题 106的解决方案使模板看起来在很大程度上是多余的。尽管如此,当无意中在模板代码中创建对引用的引用时,add_reference 可能在抑制编译器警告方面很有用。

于 2013-05-08T08:03:31.697 回答
8

这些特征是为偶尔的元使用而提供的。它使得在元编程中传输所需的 cv 限定符成为可能。

template<class T,template<class> class Trait>
struct transform
{
  /* working with T creating newT*/

  typedef Trait<newT>::type type;
};

template<class T>
struct special_transform
  : transfrom<T, std::add_const>
{};

在这种情况下,您无法替换std::add_constconst.

于 2013-06-04T06:22:53.713 回答
7

add_const可用于解决类型推导冲突。

template <typename T>
class wrapper;

template <typename T>
bool operator==(wrapper<T> const& w, T const& t);

如果我们使用,就会出现问题wrapper<T const>

wrapper<int const> w = { 42 };
assert(w == 42); // Error: conflicting deduced types

T被同时推导出为int int const。这可以使用以下方法解决add_const

template <typename T>
bool operator==(wrapper<T> const& w, add_const_t<T>& t);
于 2017-02-17T01:28:46.783 回答
1

我知道的唯一用例如下图所示:

struct F
{
    bool f() const { return true; }
    bool f() { return false; }
};
assert(!F{}.f())
assert(std::add_const_t< F >{}.f());

它还需要测试cv-ref 限定的成员函数功能,这可能因不同的重载而有所不同(仅对于 lref 限定的现代 C++ 具有方便的std::as_const功能):

struct F
{
    int g() & { return 1; }
    int g() const & { return 2; }
    int g() && { return 3; }
    int g() const && { return 4; }
};
F f;
assert(f.g() == 1);
assert(std::as_const(f).g() == 2);
assert(F{}.g() == 3);
assert(std::add_const_t< F >{}.g() == 4); // rarely needed, but if needed, then it helps
于 2016-02-21T21:14:37.083 回答