对容器中项目的常量正确指针访问
Const-correct pointer access to items in a container
问题
我有一个 class 保存指向容器的指针。该容器提供对其项目子集的访问。这是通过具有 const 和非常量版本 returning 一个 const/non-const 指针向量的方法实现的。以下代码是从更复杂的设置中摘录的最小(非完整功能)代码:
#include <vector>
struct Entity
{ int dummy; };
template <typename Value>
struct MyContainer
{
typedef Value* pointer;
typedef Value const* const_pointer;
std::vector<pointer> pointers() {
std::vector<pointer> ret;
return ret;
}
std::vector<const_pointer> pointers() const {
std::vector<const_pointer> ret;
return ret;
}
};
struct MyType
{
typedef MyContainer<Entity> ContainerType;
ContainerType* m_data; // I cannot make this a non-pointer attribute
std::vector<Entity*> pointers() {
std::vector<Entity*> ret = m_data->pointers();
return ret;
}
std::vector<Entity const*> pointers() const {
std::vector<Entity const*> ret = m_data->pointers(); // error!
return ret;
}
// std::vector<Entity*> pointers() const {
// std::vector<Entity*> ret = m_data->pointers();
// return ret;
// }
};
int main() {
MyType obj;
MyType const& constobj = obj;
std::vector<Entity*> pointers = obj.pointers();
std::vector<Entity const*> constpointers = constobj.pointers();
// std::vector<Entity*> constpointers = constobj.pointers();
}
Clang 3.8.0(也是3.5.2)报错:
error: no viable conversion from 'vector<pointer>' to 'vector<const Entity *>'
std::vector<Entity const*> ret = m_data->pointers();
^ ~~~~~~~~~~~~~~~~~~
commected 代码编译得很好,但是,我的意图是让 const 访问通过 const 访问路径(通过 constobj
)获得的项目,因此 const 方法应该 return 类型的指针Entity const*
。将 m_data
的类型从 ContainerType*
更改为 ContainerType
可以解决问题,但这不是我原始代码中的选项。
问题:
- 似乎
MyType::pointers() const
通过它的属性m_data
调用了非常量方法MyContainer::pointers()
,它的类型是MyContainer* const
(至少我是这么认为的)。我显然需要输入 MyContainer const*
。有没有优雅的解决方案来实现这一点?
- 不太优雅的解决方案是将指针转换为 const 指针:
std::vector<Entity const*> ret = static_cast<ContainerType const*>(m_data)->pointers();
这被认为是明智的解决方案吗?
- 更一般地说:是我的设计有缺陷,还是我只是遗漏了一个细节?
免责声明:
我希望这不是重复的,看来其他人之前一定遇到过同样的问题。无论如何,我无法通过阅读 SO 上的相关问题来解决这个问题。 (问题
Const correctness causing problems with containers for pointers?不同,它是关于指针的容器。这个问题似乎是相关的,但答案并没有帮助我解决目前的问题。)
写的时候
m_data->pointers()
您正在调用同一个函数(非常量函数),因为 m_data 定义为:
ContainerType* m_data;
即指向非常量对象的指针。
当你使用 constobj 时,编译器将 m_data 视为一个 const 成员(你不能更改 constobj),但在这个对象中,指针仍然指向一个非 const 对象。
我不知道你的应用程序是什么,但你可以考虑添加一个新函数作为 "cpointers" 到 return const 指针,即使对象不是 const。
编辑:我的意思是,像这样:
struct MyContainer
{
typedef Value* pointer;
typedef Value const* const_pointer;
std::vector<pointer> pointers() {
std::vector<pointer> ret;
return ret;
}
std::vector<const_pointer> pointers() const {
std::vector<const_pointer> ret;
return ret;
}
std::vector<const_pointer> cpointers() const {
std::vector<const_pointer> ret;
return ret;
}
};
struct MyType
{
typedef MyContainer<Entity> ContainerType;
ContainerType* m_data; // I cannot make this a non-pointer attribute
std::vector<Entity*> pointers() {
std::vector<Entity*> ret = m_data->pointers();
return ret;
}
std::vector<Entity const*> pointers() const {
std::vector<Entity const*> ret = m_data->cpointers(); // error!
return ret;
}
};
改变
std::vector<Entity const*> ret = m_data->pointers(); // error!
至
std::vector<Entity const*> ret =
(static_cast<const MyContainer<Entity>*>(m_data))->pointers(); // OK
问题
我有一个 class 保存指向容器的指针。该容器提供对其项目子集的访问。这是通过具有 const 和非常量版本 returning 一个 const/non-const 指针向量的方法实现的。以下代码是从更复杂的设置中摘录的最小(非完整功能)代码:
#include <vector>
struct Entity
{ int dummy; };
template <typename Value>
struct MyContainer
{
typedef Value* pointer;
typedef Value const* const_pointer;
std::vector<pointer> pointers() {
std::vector<pointer> ret;
return ret;
}
std::vector<const_pointer> pointers() const {
std::vector<const_pointer> ret;
return ret;
}
};
struct MyType
{
typedef MyContainer<Entity> ContainerType;
ContainerType* m_data; // I cannot make this a non-pointer attribute
std::vector<Entity*> pointers() {
std::vector<Entity*> ret = m_data->pointers();
return ret;
}
std::vector<Entity const*> pointers() const {
std::vector<Entity const*> ret = m_data->pointers(); // error!
return ret;
}
// std::vector<Entity*> pointers() const {
// std::vector<Entity*> ret = m_data->pointers();
// return ret;
// }
};
int main() {
MyType obj;
MyType const& constobj = obj;
std::vector<Entity*> pointers = obj.pointers();
std::vector<Entity const*> constpointers = constobj.pointers();
// std::vector<Entity*> constpointers = constobj.pointers();
}
Clang 3.8.0(也是3.5.2)报错:
error: no viable conversion from 'vector<pointer>' to 'vector<const Entity *>'
std::vector<Entity const*> ret = m_data->pointers();
^ ~~~~~~~~~~~~~~~~~~
commected 代码编译得很好,但是,我的意图是让 const 访问通过 const 访问路径(通过 constobj
)获得的项目,因此 const 方法应该 return 类型的指针Entity const*
。将 m_data
的类型从 ContainerType*
更改为 ContainerType
可以解决问题,但这不是我原始代码中的选项。
问题:
- 似乎
MyType::pointers() const
通过它的属性m_data
调用了非常量方法MyContainer::pointers()
,它的类型是MyContainer* const
(至少我是这么认为的)。我显然需要输入MyContainer const*
。有没有优雅的解决方案来实现这一点? - 不太优雅的解决方案是将指针转换为 const 指针:
std::vector<Entity const*> ret = static_cast<ContainerType const*>(m_data)->pointers();
这被认为是明智的解决方案吗? - 更一般地说:是我的设计有缺陷,还是我只是遗漏了一个细节?
免责声明: 我希望这不是重复的,看来其他人之前一定遇到过同样的问题。无论如何,我无法通过阅读 SO 上的相关问题来解决这个问题。 (问题 Const correctness causing problems with containers for pointers?不同,它是关于指针的容器。这个问题似乎是相关的,但答案并没有帮助我解决目前的问题。)
写的时候
m_data->pointers()
您正在调用同一个函数(非常量函数),因为 m_data 定义为:
ContainerType* m_data;
即指向非常量对象的指针。
当你使用 constobj 时,编译器将 m_data 视为一个 const 成员(你不能更改 constobj),但在这个对象中,指针仍然指向一个非 const 对象。
我不知道你的应用程序是什么,但你可以考虑添加一个新函数作为 "cpointers" 到 return const 指针,即使对象不是 const。
编辑:我的意思是,像这样:
struct MyContainer
{
typedef Value* pointer;
typedef Value const* const_pointer;
std::vector<pointer> pointers() {
std::vector<pointer> ret;
return ret;
}
std::vector<const_pointer> pointers() const {
std::vector<const_pointer> ret;
return ret;
}
std::vector<const_pointer> cpointers() const {
std::vector<const_pointer> ret;
return ret;
}
};
struct MyType
{
typedef MyContainer<Entity> ContainerType;
ContainerType* m_data; // I cannot make this a non-pointer attribute
std::vector<Entity*> pointers() {
std::vector<Entity*> ret = m_data->pointers();
return ret;
}
std::vector<Entity const*> pointers() const {
std::vector<Entity const*> ret = m_data->cpointers(); // error!
return ret;
}
};
改变
std::vector<Entity const*> ret = m_data->pointers(); // error!
至
std::vector<Entity const*> ret =
(static_cast<const MyContainer<Entity>*>(m_data))->pointers(); // OK