1

I have a problem when I want to check certain template-parameters for their validity using some helper struct and constepxr functions. As long as there is no reference to the static constexpr member I want to initialize the compiler decides not to evaluate the expression. The code I use is the following:

#include <cstddef> #include <iostream> #define CONSTEXPR static constexpr using namespace std; template<size_t ... Sizes> struct _size_check_impl { static_assert(sizeof...(Sizes) != 0, "Dimension has to be at least 1"); CONSTEXPR size_t dimension = sizeof...(Sizes); }; template<size_t ... Sizes> constexpr size_t check_sizes() { return _size_check_impl<Sizes...>::dimension; } template<size_t ... Sizes> struct Test { static constexpr size_t Final = check_sizes<Sizes...>(); }; int main() { Test<> a; // This shouldn't get through the static assert Test<1, 2> b; // Passing Test<2> c; // Passing // cout << Test<>::Final; // With this it works just fine, bc Final is accessed return 0; } 

Is there a way I can do this, some proxy dependecy that forces the compiler to evaluate the Final value if constexpr are evaluated? Is there another, clean way to check this property clean and quickly?

2
  • The reason is that the static assertion is dependent on the Sizes... parameter, which isn't instantiated until phase two of two phase lookup. Commented Dec 29, 2014 at 19:26
  • If Test<...>::Final is used anywhere, then its value will be evaluated. If not, it won't. Then you shouldn't care whether it is evaluated or not. Commented Dec 29, 2014 at 19:26

1 Answer 1

3

The simple answer would probably be to simply add another static_assert:

template<size_t ... Sizes> struct Test { static constexpr size_t Final = check_sizes<Sizes...>(); static_assert(Final > 0, ""); }; 

This will lead to two separate static assertion failures, though. If that is a problem for you, you could make sure check_sizes, or Final, is used some other way that must necessarily be evaluated at template class instantiation time, without instantiation of any member, for instance:

template<size_t ... Sizes> struct Test { static constexpr decltype(check_sizes<Sizes...>(), size_t()) Final = check_sizes<Sizes...>(); }; 

Yet another option: if Test<...> is a class that is expected to be constructed normally, you could make sure Final is used from the constructor somehow.

Sign up to request clarification or add additional context in comments.

1 Comment

I have gone with the first method and removed the static assert from check_sizes where it just checks that Final == 0 to avoid the two assertion fails. I also rushed so fast that I forgot about option 3, although I like the first two options more because they detect the error earlier.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.