常量成员函数中模板成员的恒定性
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
"。
Listener
内部sockets_
const
。让我们来看看front
返回的内容:
reference front();
const_reference front() const;
所以我们会得到一个const_reference
,在这种情况下是一个TcpSocket * const&
。
这就是您的期望不正确的地方。为了清楚起见,剥离引用,您期望const TcpSocket*
,它为您提供TcpSocket * const
。前者是指向const TcpSocket
的指针,后者是指向TcpSocket
的const
指针。
因此,front
给你的是一个指针,你不能改变它,你可以改变TcpSocket
。
因此,制作此指针的非常量副本及其脚尖可供修改是完全有效的:
auto s = sockets_.front();
//sockets_.front() returns TcpSocket* const
//s copies it to a TcpSocket*
说调用了 front
的非常量版本,只是您存储指针,然后将其放入始终按值推导的auto
中(而不是通过引用 - 您需要auto& =
)。因为您正在复制 const 指针,所以您拥有自己的副本,因此省略const
,除非您以这种方式显式定义它。这就是为什么你推断TcpSocket*
而不是TcpSocket* const
.
如果您想验证这一点,请尝试执行auto& s = _sockets.front()
,然后查看您得到的类型。
同样请注意,由于您正在存储指针,因此您返回vector::const_reference
将指向常量指针,而不是指向 const 的指针。
容器本身在该范围内是常量,这意味着您无法更改其元素序列或它们指向的内容。所以你不能说_sockets.erase()
也不能说_sockets[0]
.但是,由于元素本身是指向非常量TcpSocket
的指针,这意味着您可以对它们做任何您想做的事情。这是你不能摆弄的容器。
即使std::vector< TcpSocket* > sockets_;
本身是const
,被包含者(即 TcpSocket*
) 不是const
。
这就是为什么你会得到非const
扣除。
为什么你没有得到TcpSocket * const
:
虽然front()
返回TcpSocket* 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
反正你是在做一份副本,那为什么那份副本会const
呢?你不会从s
被TcpSocket * const
中获得任何有价值的东西。
为什么你没有得到TcpSocket const *
:
这只是因为您将TcpSocket*
存储在向量中。front()
的const
性确保存储的指针不被改变(即你不能sockets_.front()
从Listener()
内指向另一个TcpSocket
),但维护所指向对象的const
正确性是由于用户。
- 将成员变量添加到共享库中的类中,不会破坏二进制兼容性吗
- 对RValue对象调用的LValue ref限定成员函数
- 指针类型类成员的动态强制转换的恒定性是什么?
- 自动模板参数、数据成员和恒常性
- 为什么对引用的常量引用会失去其恒定性?
- 引用类型的数据成员提供有关恒常正确性"loophole"
- 运算符的要求<恒定性在标准::stable_sort
- 模板参数推导由于恒定性不一致而失败
- 为什么模板参数失去恒定性?
- 为什么普遍引用不保持其论点的恒定性
- 是否可以使用 SFINAE 检测类方法的恒定性?
- 在模板中强制转换为引用似乎会抛弃恒定性
- 在分配对象时保持恒定性
- 常量成员函数中模板成员的恒定性
- 变量的恒定性及其生存期
- 尊重恒定性,同时避免在堆上重新分配
- C++ - 为什么常量函数不强制成员指针上的恒常性?
- 参考类成员的恒定性
- 当函数参数常量引用 T 时,为什么 T 的模板参数推导'skips'数组元素的恒定性?
- 从"this"中抛弃恒常性,然后更改成员值是否会调用未定义的行为?