std::reference_wrapper的常量正确性是否违反C++23标准规则?
关于const限定的std::reference_wrapper是否违反C++23 [res.on.data.races]#3条款的疑问
const限定的std::reference_wrapper<T>行为类似引用或者T* const,示例代码如下:
#include <functional> struct S { void operator()() { i++; } int i = 0; }; int main() { S s; const std::reference_wrapper<S> r = s; // 此时 s.i == 0 r(); // 此时 s.i == 1 S* const p = &s; // 此时 s.i == 1 (*p)(); // 此时 s.i == 2 }
变量r是const的,且std::reference_wrapper::operator()是const成员函数,因此可以调用它,而这会修改被指向的对象。但该operator()是标准库函数,因此C++23标准中的[res.on.data.races]#3条款适用于它:
C++标准库函数不得直接或间接修改当前线程以外的线程可访问的对象(见[intro.multithread]),除非这些对象是通过函数的非const参数(包括
this)直接或间接访问的。
请问std::reference_wrapper是否违反了该规则?
回答
没有违反该规则,原因如下:
std::reference_wrapper的设计目标是作为引用的可复制包装器,它的const成员函数(比如operator())本质是通过内部持有的引用代理操作被包装的对象。这里被修改的并非const std::reference_wrapper自身,而是它绑定的外部对象S。- [res.on.data.races]#3条款的核心约束是:禁止标准库函数在未通过非const参数(包括
this)授权的情况下,修改跨线程可访问的外部对象。而在这个场景中,用户通过std::reference_wrapper调用operator(),本质是明确要求修改自己提供的被引用对象,标准库只是执行了用户的意图,并非擅自修改外部状态。 - 从语义上看,
const std::reference_wrapper<S>等价于const S&(引用本身不可重绑定,但可修改非const的被引用对象)或S* const(指针本身不可改指向,但可解引用修改对象),这种行为完全符合C++中引用和指针的既定语义,标准库的实现只是遵循了这一语义,并未违反条款。
内容的提问来源于stack exchange,提问作者Dr. Gut
相关产品推荐
相关产品推荐

