私の目的は、完全には壊れていないかもしれませんが、少なくとも完全に動作するコンストラクタ/デストラクタのペアとstd::get<>()
関数を書くことです。std :: variant-likeクラスを実装するときにタイプタグを保存する際の問題
文字配列を使用してメモリを予約しようとしました。それのサイズは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?
}
};
私は問題につまずいた。私はオブジェクトが死ぬときにどのデストラクタを実行するのか分かりません。その上に、適切なタイプを得るためにstd::get<>()
を特化することはできないので、基礎となるオブジェクトにアクセスすることは不可能です。
私の質問は:どのようにオブジェクトの作成後に型を格納するのですか?それは正しいアプローチですか?そうでない場合、私は何を使うべきですか?
EDIT:
私はコメントを適用しようとしました。問題は、現在生きている型のインデックスはconstexpr
にできないため、型リストから必要な型を抽出して適切なデストラクタを呼び出すことができないということです。
~variant()
{
using T = typename extract<index, alternatives...>::type;
(T*)&object[0]->~T();
}
EDIT:
私は、ベースラインの実装を行いました。それは機能しますが、欠けている機能がたくさんあります。あなたはそれを見つけることができますhere。レビューをいただき、うれしく思いますが、最初にhow do I write a good answer?とお読みください。
バリアントがそれで生きているオブジェクトの種類を追跡します。例えば。 [索引](http://en.cppreference.com/w/cpp/utility/variant/index)。 – Columbo
@Columbo、それを試してみましょう。私はis_presentを再実装し、インデックス – Incomputable
を返します。また、['std :: aligned_union' exists](http://en.cppreference.com/w/cpp/types/aligned_union)。 –