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;
};
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With