const 成员函数中模板成员的常量

Constness of template member in const member function

如何将 const 应用于 const 成员函数中的模板成员?我发现以下内容很有趣(这是在 VS15 中):

class TcpSocket;

class TcpThread
{
   TcpSocket* Listener() const;
   std::vector< TcpSocket* > sockets_;
};

TcpSocket* TcpThread::Listener() const
{
   auto s = sockets_.front();
   return s;
}

我添加了 auto 以阐明发生了什么。它被推断为 TcpSocket*,因此正在选择 front 的非常量版本。但是,如果我插入

sockets_.erase(sockets_.begin());

作为第一行代码,它编译失败,本质上说 sockets_const.

它按原样工作是有意义的,但显然这里发生的不仅仅是“将每个成员视为 const 成员函数中的 const

即使 std::vector< TcpSocket* > sockets_; 本身 const,容器(即 TcpSocket*)是 而不是 const.

这就是您获得非const 扣除的原因。

并不是调用了 front 的 non-const 版本,只是你在存储指针,然后将它放入 auto 中,它总是推导 by-value(而不是引用——你需要 auto& =)。因为您正在复制 const 指针,所以您拥有自己的副本,因此省略了 const ,除非您以这种方式明确定义它。这就是为什么你推导 TcpSocket* 而不是 TcpSocket* const.

如果您想验证这一点,请尝试执行 auto& s = _sockets.front() 并查看您得到的类型 然后

注意。同样,因为你正在存储一个指针,所以你返回的 vector::const_reference 将指向一个 const 指针 而不是 指向 const 的指针.

container 本身在该范围内是 const,这意味着您无法更改其元素序列或它们指向的内容。所以你不能说 _sockets.erase() 也不能说 _sockets[0]但是,因为元素本身是指向 non-const TcpSocket 的指针,这意味着您几乎可以用它们做任何您想做的事情。这是 容器 你不能 fiddle 用。

sockets_Listener 里面是 const。让我们看看 front returns:

reference front();
const_reference front() const;

所以我们会得到 const_reference,在本例中是 TcpSocket * const&

这是您的期望不正确的地方。为了清楚起见,去掉引用,你期望 const TcpSocket*,它给你 TcpSocket * const。前者是指向const TcpSocket的指针,后者是const指向TcpSocket.

的指针

那么 front 给你的是一个指针,你无法将其更改为 可以 更改的 TcpSocket

因此,制作此指针的 non-const 副本及其指针对象可用于修改是完全有效的:

auto s = sockets_.front();
//sockets_.front() returns TcpSocket* const
//s copies it to a TcpSocket*

为什么你没有得到TcpSocket * const:

虽然front()returnsTcpSocket* const &,但auto推导为TcpSocket*.

考虑:

double const & foo(); 
// ...
double const a = 4.0;
auto b = a; // valid, decltype(b) === double
double c = a; // valid, too
double d = foo(); // valid
auto e = foo(); // decltype(e) === double

反正你是在制作一个副本,那为什么那个副本是 consts 成为 TcpSocket * const.

不会让你得到任何有价值的东西

为什么你没有得到 TcpSocket const *:

那只是因为您将 TcpSocket* 存储在向量中。 front()const 确保存储的指针不被改变(即你不能使 sockets_.front()Listener() 中指向另一个 TcpSocket)但维护const-指向的对象的正确性是由于用户。