繁体   English   中英

std :: add_const和类似的用例

[英]Use cases for std::add_const and similar

<type_traits>某些类型转换也可以使用核心语言语法来表示(例如std::add_const<T>::type is /似乎与const T等效)。 Dtto代表std::add_lvalue_reference ,也许还有其他。 这些类型特征有什么用?

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

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

Apply<int, std::add_const>

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

这些特性来自Boost以及将其添加到标准N1345中的提议 ,引用了Andrei Alexandrescu的话:

“我理解添加add_constadd_volatileadd_cvadd_pointer ,但是我主张消除它们。语言提供的等效项只是更简单,更好。”

相同的建议也给出了以下理由:

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

另外,对于add_reference (在标准中重命名为add_lvalue_reference ):

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

这些特征仅供偶尔使用。 这使得在元编程中传输所需的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_const替换为const

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);

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM