3 ms·
I agree that constexpr if looks great. I am confused about the decision on how to handle static_assert. It seems that if constexpr (false) { static_asser
by toth 10y ago
I agree that constexpr if looks great. I am confused about the decision on how to handle static_assert. It seems that
if constexpr (false) { static_assert(false); }
Will fail to compile because the static_assert will trigger. This seems strange to me, anybody have an idea what the reasoning here is?
- lorenzhs 10y agoI think it's only consistent. Static assertions should always always always hold (things like type checks etc), if you really want to only evaluate it in that branch you can still do if constexpr (foo) { static_assert(!foo || /* assertion */); } else { static_assert(foo || /* assertion */); } (this gets ugly fast with lots of else-ifs, but it's a workaround - I don't know why you'd ever need it, though)
- toth 10y agoHmm, it seems this constexpr if is much more limited than I realized then. If I understood correctly the code in the the body of the constexpr if has to be correct even if the condition does not hold. I.e., this code: template<typename T> void func(T x) { if constexpr ( std::is_same< T, ClassWithMemberF>::value ) { x.f(); } } will not work if you pass in a type for x that does not have a member function f. Is my understanding right? If so, constexpr if is not nearly as nice as I thought...
- RcouF1uZ4gsC 10y agoIn my reading of it, this code would work. The code in if constexpr must be well-formed but does not have to be semantically valid. Your code is well-formed but not semantically valid, so this would be the perfect use for if constexpr
- toth 10y agoYou may be correct, and I certainly hope you are. But if that's the case then the static_assert behavior seems all the more puzzling. In particular if this code works, then you can roll your own "static_assert" that will not trigger from the not taken branches.
- revelation 10y agoconstexpr isn't mean to replace the preprocessor. This will not compile for the same reason that if (false constexpr) { random gibberish } will not compile, and that's a good thing. I think it would be odd to "hack" static_assert for this special case.
- toth 10y agoOpinions differ I guess. I would love it if if constexpr ( COND) { CODE }; would compile even if CODE only compiles when COND is true. There a lot of nice use cases for that, and that's how the static_if in D works. You can still do this sort of stuff with template overloads, but it's much more cumbersome.
- Kristine1975 10y agoThat's the case though, as long as CODE is syntactically correct. So this would compile: if constexpr (condition) { print("yes"); } While this wouldn't: if constexpr (condition) { print({ } At least that's my understanding.
- saynsedit 10y agoSince the intended use of constexpr if is to block template instantiations, static_assert is kind of orthogonal to that. static_asserts in non-instantiated templates are ignored, as you would expect.
- toth 10y agoYou are saying that static_assert would not trigger here, correct? That makes sense to me, but it's not what is in the proposal [1] - see the "Not proposed" section. [1] http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0292r1.html http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p029...
- saynsedit 10y agoNo, I'm saying static_assert in non-instantiated templates would not trigger. template<class T> class foo; template<> class foo<int> { static_assert(false, "bad"); }; template<> class foo<float> {}; template<class T> foo<T> foo_fn(T v) { if constexpr (std::is_same<T, int>::value) { return foo<int>{}; } else if constexpr (std::is_same<T, float>::value) { return foo<float>{}; } else { return foo<T>{}; } } foo_fn(1.0); // <-- does not trigger static assert foo_fn(1); // <-- triggers static assert This is consistent with the wording of the proposal.
- Kristine1975 10y agoThis does not compile: template<> class foo<int> { static_assert(false, "bad"); }; Reason: "false" is not a dependent name, so the compiler is allowed to check the static_assert when the template is being declared. (Of course since this is a full specialization, there are no dependent names.) See C++14 Standard §14.6.2 (Dependent Names) or http://en.cppreference.com/w/cpp/language/dependent_name http://en.cppreference.com/w/cpp/language/dependent_name (not sure how accurate that page is, though). P.S: It might compile with Microsoft's Visual Studio, but only because that compiler doesn't implement two-phase name lookup, effectively turning every name into a dependent name.