Reputation: 1776
I'm writing a simple implementation for a Variant class, but Visual Studio rejects this code when I try to instantiate a variable of type AlignedStorage:
using std::size_t;
template <size_t SIZE, size_t... ALIGNMENT>
struct AlignedStorage
{
struct Type
{
alignas(ALIGNMENT...) unsigned char storage[SIZE];
};
};
template <size_t SIZE, size_t... ALIGNMENT>
using AlignedStorageT = typename AlignedStorage<SIZE, ALIGNMENT...>::Type;
/**** variant storage class ****/
template <typename... Types>
class VariantStorage
{
public:
void *GetStorage() { return mStorage.storage; }
const void *GetStorage() const { return mStorage.storage; }
template <typename T>
T &GetStorageAs() { return *reinterpret_cast<T*>(GetStorage()); }
template <typename T>
const T &GetStorageAs() const { return *reinterpret_cast<const T*>(GetStorage()); }
unsigned GetDiscriminator() const { return mDiscriminator; }
void SetDiscriminator(unsigned discriminator) { mDiscriminator = discriminator; }
private:
using LargestT = typename LargestType<Typelist<Types...>>::Type;
AlignedStorageT<sizeof(LargestT), alignof(Types)...> mStorage; ///////// Visual studio ERROR (not GCC)
unsigned int mDiscriminator; // discriminated union tag
};
it seems to have issues with the ALIGNMENT pack expansion, Gcc seems to work fine, but it rejects this other line (which seems to be fine with VC++):
template <typename T, typename V> // CRTP
class VariantChoice;
template <typename...>
class Variant;
template <typename Type, typename... Types>
class VariantChoice<Type, Variant<Types...>>
{
friend class Variant<Types...>; // private ctor
protected:
static constexpr unsigned int mDiscriminatorIndex = IndexOfType<Type, Typelist<Types...>>::Value; // index of Type in typelist
private:
VariantChoice() = default;
~VariantChoice() = default;
VariantChoice(const VariantChoice &other);
VariantChoice(VariantChoice &&other);
VariantChoice &operator=(const VariantChoice &other);
VariantChoice &operator=(VariantChoice &&other);
using Derived = Variant<Types...>; // CRTP
Derived &AsDerived() { return static_cast<Derived&>(*this); }
const Derived &AsDerived() const { return static_cast<Derived const&>(*this); }
};
/**** variant class ****/
template <typename... Types>
class Variant : VariantStorage<Types...>, VariantChoice<Types, Variant<Types...>>...
{
template <typename, typename>
friend class VariantChoice; // enable CRTP (private inheritance)
public:
using VariantChoice<Types, Variant>::VariantChoice...; // inherited ctors
Variant() {}
Variant(const Variant &other);
Variant(Variant &&other);
template <template <typename...> class Variant_, typename... Types_>
Variant(Variant_<Types_...> &&other);
using VariantChoice<Types, Variant>::operator=...; ///////// GCC ERROR: bring copy/move assignment operators in scope doesn't compile ???? (VC++ works)
Variant &operator=(Variant const &other);
Variant &operator=(Variant &&other);
private:
};
Is this code correct? Or Am I doing something not standard?
EDIT I corrected alignof(Types)...
Upvotes: 1
Views: 180
Reputation: 1
For the issue of using VariantChoice<Types, Variant>::operator=...
not work with gcc you should update gcc to at least gcc10
, I used ubuntu with gcc9.3
and got the same problem. when I upgraded to gcc12
, everything was fine.
Upvotes: 0