我们需要std :: as_const()做什么?

时间:2018-11-23 16:46:48

标签: c++ const c++17 typetraits rationale

C ++ 11给了我们std::add_const;使用C ++ 17,我们有了一个新结构-std::as_const()。前者只是在您提供的类型之前加上const。第二个是适当的(一个a的模板)函数,而不是类型特征,它似乎可以做到这一点-除了当类型是右值引用时(在这种情况下,它不能使用)。

我不太了解提供std::as_const()的动机。为什么除了std::add_const之外还需要它?

2 个答案:

答案 0 :(得分:20)

“需要”是一个很强的词... std::as_const之所以存在是因为它很有用,并非严格必要。由于它是一个函数而不是特征,因此我们可以使用它为实际的而不是 types 添加const。

更具体地说:假设我有一些变量my_value,并且我想将其视为const,但不要复制它。在C ++ 17之前,我需要写:

static_cast<const MyType&>(my_value)

如果我不想明确指定类型,则为:

static_cast<std::add_const_t<std::remove_reference_t<decltype(my_value)>> &>(my_value)

或者如果您想弄脏并且使用C型铸造:

(const decltype(my_value) &) (my_value)

所有这些都很烦人和冗长。

代替这些,现在使用C ++ 17编写std::as_const(my_value),仅此而已。

注意:

  • 对于右值引用,此功能已被禁用,即使对它们而言也很好。原因是为了帮助您避免在无意间破坏对临时性的引用。正如@NicolBolas解释的那样,如果您编写类似以下内容:

    for(auto &x : std::as_const(returns_container())) { /* do stuff with x */ }
    

    然后,返回的容器的生存期在循环的第一次迭代之前结束。很容易错过!

  • 有关其他(?)信息,请参考该实用函数的正式命题:P007R1,由Adam David Alan Martin和Alisdair Meredith撰写。

答案 1 :(得分:1)

您可能想重载const,no-const并强制之一或重载:

template<class T> [[nodiscard]]
T twice(T const& t){return t + t;}

template<class T>
void twice(T& t){return t += t;}

您可以通过添加const来保护输入并使用非修改重载。

double t = 5.;
twice(t); // t == 10

doble const u = 5.;
double ux2 = twice(u); // ux2 == 10, u == 5.;

double v = 5.;
double vx2 = twice(std::as_const(v)); // vx2 == 10., v==5. It saves you from creating a const-reference `double const& ucr = u;` just to pass to the function.

我并不是说这是一个好的设计,只是为了说明这一点。 寻找一个更有用的案例只是时间问题。

std::as_const是IMO的更好称呼。{strong>