Inc*_*ble 14 c++ templates variant c++17
我的目标是写std::variant,可能没有完全吹,但至少与完全工作的构造函数/析构函数对和std::get<>()函数.
我试图使用char数组保留一个内存.它的大小由最大类型决定,通过使用find_biggest_size<>()函数找到.构造函数使用静态断言,因为它执行检查类型是否在指定类型的列表中.现在,构造函数和就地构造函数工作.
template <typename ... alternatives>
class variant
{
char object[find_biggest_size<alternatives...>::value];
public:
template <typename T>
variant(T&& other)
{
static_assert(is_present<T, alternatives...>::value, "type is not in range");
new ((T*)&object[0]) T(std::forward<T>(other));
}
template <typename T, typename ... ArgTypes>
variant(in_place_t<T>, ArgTypes&& ... args)
{
static_assert(is_present<T, alternatives...>::value, "type is not in range");
new ((T*)&object[0]) T(std::forward<ArgTypes>(args)...);
}
~variant()
{
// what to do here?
}
};
Run Code Online (Sandbox Code Playgroud)
然后我偶然发现了一个问题.我不知道当对象死亡时要执行什么析构函数.最重要的是,不可能访问底层对象,因为我无法专门std::get<>()获得正确的类型.
我的问题是:如何在创建对象后存储类型?这是正确的方法吗?如果没有,我应该使用什么?
编辑:
我试图应用评论.问题是当前存活的类型的索引不能constexpr,因此我无法从类型列表中提取所需的类型并调用适当的析构函数.
~variant()
{
using T = typename extract<index, alternatives...>::type;
(T*)&object[0]->~T();
}
Run Code Online (Sandbox Code Playgroud)
编辑:
我做了一个基线实现.它有效,但有很多缺少的功能.你可以在这里找到它.我很乐意收到评论,但请先阅读如何写出一个好的答案?.
Ric*_*ges 11
我怎么可能开始:
#include <iostream>
#include <utility>
#include <array>
template<class...Types>
struct variant
{
variant() {}
~variant()
{
if (type_ >= 0)
{
invoke_destructor(type_, reinterpret_cast<char*>(std::addressof(storage_)));
}
}
template<class T> static void invoke_destructor_impl(char* object)
{
auto pt = reinterpret_cast<T*>(object);
pt->~T();
}
static void invoke_destructor(int type, char* address)
{
static const std::array<void (*)(char*), sizeof...(Types)> destructors
{
std::addressof(invoke_destructor_impl<Types>)...
};
destructors[type](address);
}
std::aligned_union_t<0, Types...> storage_;
int type_ = -1;
};
int main()
{
variant<int, std::string> v;
}
Run Code Online (Sandbox Code Playgroud)