C ++ 11给了我们std::add_const
;使用C ++ 17,我们有了一个新结构-std::as_const()
。前者只是在您提供的类型之前加上const
。第二个是适当的(一个a的模板)函数,而不是类型特征,它似乎可以做到这一点-除了当类型是右值引用时(在这种情况下,它不能使用)。
我不太了解提供std::as_const()
的动机。为什么除了std::add_const
之外还需要它?
答案 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>