Joh*_* Li 4 c++ pointers boost-any heterogeneous-array
在C中,可以将数据指针分配给void指针,然后将其转换回原始类型,该数据指针将被恢复.语言标准保证这种转换不会丢失信息.这通常意味着(不一定,但对大多数平台来说都是如此),void指针的大小与数据指针的大小相同.因此,可以指望这些事实使用void指针作为异构类型的一般指针,而void指针本身具有统一的大小和表示.例如,一个有一个void指针数组,其元素指向动态分配的不同类型的对象.构造这样的数组使某些事情变得方便.我的问题是:如何实现类似的东西,C++中的通用指针类型,它符合以下内容:(假设g_pointer是类名)
从任何指针类型构造,可以编写类似的代码
g_pointer g_ptr = g_pointer(new T())
Run Code Online (Sandbox Code Playgroud)恢复原始指针
T* ptr = g_ptr.recover(), or
auto* ptr = g_tr.recover()
Run Code Online (Sandbox Code Playgroud)更新:根据一些评论,上面的内容无法用C++完成,那就像是
recover<Type>(g_ptr)
Run Code Online (Sandbox Code Playgroud)
应该足够了,抛出异常Type不兼容.
g_pointer可以包含在std :: vector或plain数组中,这基本上就是指
sizeof(g_pointer) // a predetermined constant number,
Run Code Online (Sandbox Code Playgroud)
(更新:这总是如此,只要这样一个类可以正确实现,感谢指出.)
我刚刚发现了boost :: any,看看它的介绍看起来似乎可能是我想要的,尽管可能不是这样.所以任何熟悉boost :: any的人都欢迎发表评论.
更新:(回复一些评论)
更新:谢谢@Caleth,std :: any很棒.
在C++中是不可能的.因为表达式的类型g_ptr.recover()是在编译时确定的,所以它不能存储在运行时确定的基础类型的信息.
如果你可以容忍像这样的表达式g_ptr.recover<T>(),你可以g_pointer通过包装a void*和a 来实现,const std::type_info&它存储指针指向的实际类型的信息,例如
class g_pointer {
public:
template <class T>
constexpr g_pointer(T *data) noexcept : _data(data), _object_type(typeid(T)) {}
template <class T>
T* recover() const {
if (typeid(T) == _object_type) return static_cast<T*>(_data);
else throw std::bad_cast{};
}
private:
void *_data;
const std::type_info &_object_type;
};
Run Code Online (Sandbox Code Playgroud)
请注意,此g_pointer行为类似于原始指针而非智能指针,这意味着它不拥有它指向的对象.
上面的实现中仍然存在一个缺陷:const T*无法隐式转换为void*,因此一般指针不能成立const T*.要处理const限定符,您可以在恢复时更改_datato 的类型const void*并使用它const_cast.另外,recover应该拒绝从g_pointer持有指向const对象的指针返回指向非const对象的指针.但是,typeid运算符忽略顶级const限定符,因此我们需要一个额外的数据成员来记录指针是否指向最初的const对象.
class g_pointer {
public:
template <class T>
constexpr g_pointer(T *data) noexcept : _data(data),
_object_type(typeid(T)),
_is_const(std::is_const_v<T>)
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ change here
{
}
template <class T>
T* recover() const {
if (
typeid(T) != _object_type ||
(_is_const && !std::is_const_v<T>) // try to obtain T* while const T* is held
) {
throw std::bad_cast{};
}
else return static_cast<T*>(const_cast<void*>(_data));
// ^^^^^^^^^^^^^^^^^ change here
}
private:
const void *_data;
// ^^^^^ change here
const std::type_info &_object_type;
bool _is_const; // <-- record whether the pointer points to const T
};
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
702 次 |
| 最近记录: |