Luca
Luca

Reputation: 1776

alignas with pack expansion not working in Visual Studio 2019?

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

Answers (1)

Yang Wei
Yang Wei

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

Related Questions