Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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;
};
like image 732
Justin Avatar asked May 25 '17 07:05

Justin


1 Answers

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.

like image 111
Angew is no longer proud of SO Avatar answered Sep 21 '22 14:09

Angew is no longer proud of SO