为什么指针类型没有 std::as_const 重载

Why no std::as_const overload for pointer types

我刚遇到 std::as_const,我对以下代码段中最后一行的输出感到惊讶:

#include <cstdio>
#include <utility>

struct S {
    void foo() { std::puts("foo: non const"); }
    void foo() const { std::puts("foo: const"); }
};

int main() {
    S s;
    s.foo(); // foo: non const
    std::as_const(s).foo(); // foo: const

    auto* s_ptr = &s;
    s_ptr->foo(); // foo: non const
    std::as_const(s_ptr)->foo(); // foo: non const (?)
}

查看文档,我明白了为什么调用 foo 的非 const 重载: std::as_const(s_ptr) returns a S* const&,即对常量的引用 指向非常量 S 的指针,而不是 S const*,即指向常量 S 的指针,就像我希望的那样 有所期待。

所以,我的问题是为什么标准不也为指针类型提供 std::as_const 重载?例如。类似于:

template <class T>
constexpr std::add_const_t<T>* as_const(T* t) noexcept {
    return t;
}

编辑: 论文 P0007R1 std::as_const 的动机之一是选择函数重载而不必求助于 const_cast. P0007R1 提供了这个例子:

int processEmployees( std::vector< Employee > &employeeList );
bool processEmployees( const std::vector< Employee > &employeeList );

A larger project often needs to call functions, like processEmployees, and selecting among specific const or non-const overloads. [...]

这就是为什么我有点惊讶它在以下情况下对重载解决没有帮助 应用于我发布的代码中的指针,也不应用于:

std::as_const(this)->foo();

也不选择以下重载中的后者:

int processEmployees( std::vector< Employee > *employeeList );
bool processEmployees( const std::vector< Employee > *employeeList );

std::as_const 的目的是能够将非 const 左值引用为 const 左值,以便它在它所在的上下文中不可修改用过的。换句话说 std::as_const(x) 应该是一个 shorthand 用于写

const auto& y = x;

然后使用 y.

它已经做得很好了,所以不需要指针的特殊行为。

这是一个简单的例子,其中建议的额外过载会产生严重的负面影响:

std::vector<int> vec = /*...*/;
for(auto it = std::begin(vec); it != std::end(vec); it++)
    func(std::as_const(it));

这里的目的是确保函数 func 不能修改 it,因为迭代向量的责任在于 for 循环。如果 func 只是采用迭代器 by-value 或 const 引用,那么 std::as_const 不是严格要求的,但无论如何作为安全措施还是有意义的,因为有多个重载func,其中一些确实修改了他们的论点。

auto 这是一些迭代器类型。它可能是一个指针。或者它可以是 class 类型。根据您建议的 as_const 重载,这会中断,具体取决于 std::vector 迭代器的实现方式。

std::as_const(it) 应该说 it 不应通过这种使用进行修改。它不应该说明对象 it 引用是否可修改。这不是它的目的。当然,添加一个使 referenced 对象 non-modifiable 的函数是有意义的。但是它应该有一个不同的名字,你可能想要为任意迭代器实现它,而不是专门为指针。基本上,一个 iterator-to-const-迭代器适配器。