【发布时间】:2015-09-04 02:33:24
【问题描述】:
我在我的代码中围绕一个对象创建了一个包装器,该包装器应该修改对该对象的访问。我选择在这里使用对象进行测试,而不是使用具有相同功能的仿函数。基本上:包装器接收对对象的引用并转发对对象的所有索引访问(在一些可能的操作之后)
现在问题来了:访问器丢弃了被包装对象的常量。
最小的例子
struct Foo
{
std::array<int, 2> data;
const int& operator()(int idx) const{
return data[idx];
}
int& operator()(int idx){
return data[idx];
}
};
struct Bar
{
Foo& ref;
Bar(Foo& r):ref(r){}
int& operator()(int idx) const{
return ref(idx);
}
};
template< typename T >
void test(const T& data){
data(1) = 4;
std::cout << data(1);
}
void main(){
Foo f;
test(f);
// Above call does not compile (as expected)
// (assignment of read-only location)
Bar b(f);
test(b); // This does compile and works (data is modified)
}
将 Bar(包装器)的 () 运算符声明为“const”,我希望所有成员都可以访问“const”。所以应该不可能返回一个“int&”,而只能返回一个“const int&”
但是 gcc4.7 可以愉快地编译代码并且忽略 const。这是正确的行为吗?这是在哪里指定的?
编辑: 关于一个相关问题:如果在 Foo 中使用 typedef,例如:
struct Foo
{
using Ref = int&;
using ConstRef = const int&; //1
using ConstRef = const Ref; //2
int* data; // Use int* to have same issue as with refs
ConstRef operator()(int idx) const{
return data[idx]; // This is possible due to the same "bug" as with the ref in Bar
}
Ref operator()(int idx){
return data[idx];
}
};
我注意到 //1 确实按预期工作,但 //2 没有。返回值仍然可以修改。他们不应该一样吗?
【问题讨论】:
-
这是正确的行为。我不会回答这个问题,因为我不想费心从标准中查找引用,但基本上你的成员变量是引用本身,而不是被引用的 int。所以在你的 operator() const 中,引用成员“ref”没有被修改,只有它引用的 Foo。我认为 C++17 会有 const 传播指针和引用。
标签: c++ c++11 reference compiler-errors constants