ein*_*ica 19 c++ const rationale type-traits c++17
C++ 11给了我们std::add_const; 使用C++ 17,我们有了一个新的结构 - std::as_const().前者只是const在你提供的类型之前添加了一个.第二个是函数的正确(模板),而不是类型特征,它似乎也是一样 - 除了类型是rvalue-reference时,在这种情况下它不能被使用.
我不太明白提供的动机std::as_const().为什么我们除此之外还需要它std::add_const?
ein*_*ica 20
"需要"是一个强有力的词...... std::as_const存在是因为它有用,而不是绝对必要.因为它是一个函数而不是一个特征,我们可以用它来"添加const"到实际值而不是类型.
更具体地说:假设我有一些变量my_value,我想把它当作a const,但不要复制它.在C++ 17之前,我需要写:
static_cast<const MyType&>(my_value)
Run Code Online (Sandbox Code Playgroud)
如果我不想明确指定类型,它将是:
static_cast<std::add_const_t<std::remove_reference_t<decltype(my_value)>> &>(my_value)
Run Code Online (Sandbox Code Playgroud)
或者如果你想变得肮脏,并使用C风格的铸造:
(const decltype(my_value) &) (my_value)
Run Code Online (Sandbox Code Playgroud)
所有这些都令人烦恼和冗长.
而不是这些,用C++ 17现在写std::as_const(my_value),这就是它的全部.
笔记:
对于右值引用,此函数被禁用,即使它对它们工作正常.原因是为了帮助你避免无意中提到一个临时的破坏.正如@NicolBolas解释的那样,如果你写的东西如下:
for(auto &x : std::as_const(returns_container())) { /* do stuff with x */ }
Run Code Online (Sandbox Code Playgroud)
然后返回的容器的生命周期在循环的第一次迭代之前结束.很容易错过!
有关其他(?)信息,请参阅此实用功能的官方提议:P007R1,Adam David Alan Martin和Alisdair Meredith.
您可能想要重载 const、no-const 并强制重载之一:
template<class T> [[nodiscard]]
T twice(T const& t){return t + t;}
template<class T>
void twice(T& t){t += t;}
Run Code Online (Sandbox Code Playgroud)
const您可以通过添加和使用非修改过载来保护输入。
double t = 5.;
twice(t); // t == 10
double 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.
Run Code Online (Sandbox Code Playgroud)
我并不是说这是一个好的设计,只是为了说明这一点。找到更有用的案例只是时间问题。
std::as_constIMO可能是一个更好的名字std::protect。