std :: add_const和类似的用例

时间:2013-05-08 07:38:00

标签: c++ c++11 language-lawyer

<type_traits>中的某些类型转换也可以使用核心语言语法表示(例如std::add_const<T>::type /似乎等同于const T)。 std::add_lvalue_reference和其他人的Dtto。这些类型特征有什么用?

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

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

Apply<int, std::add_const>

这些特征是否还有其他可以在语法上表达的用例,或者它们是否仅仅是“出于完整感”和偶尔的元使用?

4 个答案:

答案 0 :(得分:23)

这些特征来自Boost,并且将其添加到标准中的提议N1345引用Andrei Alexandrescu的话说:

  

“我理解添加add_constadd_volatileadd_cvadd_pointer的对称性论点,不过我会主张删除它们。语言提供等价物更简单,更好。“

同样的提案也提供了这个理由:

  

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

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

  

作者注:add_reference模板是boost类型特征库背后的原始动机之一。但是,issue 295的分辨率使模板显得多余。尽管add_reference可能在无意中在模板代码中创建对引用的引用时抑制编译器警告。

答案 1 :(得分: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_const替换为const

答案 2 :(得分:5)

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

答案 3 :(得分:1)

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

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

它还需要测试 cv-ref-qualified 成员函数功能,这些功能可能因不同的重载而不同(仅适用于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