Justin
Justin

Reputation: 25337

How do I delay the instantiation of a static data member in Visual C++?

The following code works with GCC and Clang, but not with Visual C++:

#include <type_traits>

struct MyType {
    static constexpr std::size_t it = 10;
};

struct MyType2 {
};

template<typename T>
struct Type2 {
    static constexpr std::size_t it = T::it;
};

int main() {
    Type2<MyType> t1;
    Type2<MyType2> t2; // Visual C++ complains that MyType2::it doesn't exist
    (void) t1;
    (void) t2;
}

According to section 14.7.1 of the standard:

... the initialization (and any associated side-effects) of a static data member does not occur unless the static data member is itself used in a way that requires the definition of the static data member to exist

So it seems that this is a bug in Visual C++; it should be accepting this code.

Regardless, I still want to be able to do this using Visual C++. What is the easiest way to allow Visual C++ to work, without changing the syntax of accessing the member variable? I also require that Type2<T>::it doesn't exist when T::it doesn't exist, or that it is otherwise possible to SFINAE off of the existance of Type2<T>::it.


This changes the syntax, so I don't want it:

template<typename T>
struct Type2 {
    template<typename = void>
    static constexpr std::size_t it = T::it;
};

// Type2<MyType>::it<>

This is a lot of work, because my class will contain more than a simple constexpr variable:

template<typename T, typename = void>
struct Type2 {
};

template<typename T>
struct Type2<T, decltype((void) T::it)> {
    static constexpr std::size_t it = T::it;
};

Upvotes: 8

Views: 246

Answers (1)

You could inherit it (when it exists) instead of declaring it directly:

template<typename T, typename = void>
struct ItHolder
{};

template<typename T>
struct ItHolder<T, decltype((void) T::it)> {
    static constexpr std::size_t it = T::it;
};


template<typename T>
struct Type2 : ItHolder<T> {
};

In other words, just take what you already suggested and combine it using another layer of indirection.

Upvotes: 2

Related Questions