Reputation: 1685
I have a class that can inherit from an empty struct or from a struct with some members, depending on a bool
. Using that same bool
, I am adding an if constexpr
block to access the members of the base class, but I am getting a compiler error
struct A{};
struct B{};
struct C{};
template <typename J0, typename J1>
struct HasFriction {
constexpr static bool value = false;
};
template <> struct HasFriction<A,B> {
constexpr static bool value = true;
};
template <bool> struct Friction { };
template <> struct Friction<true> { int value = 4; };
template <typename J0, typename J1>
struct MyStruct : public Friction<HasFriction<J0, J1>::value> {};
int main()
{
if constexpr (HasFriction<A, C>::value) {
MyStruct<A,C> f;
return f.value;
} else {
MyStruct<A,C> no_f;
return 0;
}
}
Why is this not working, and how should I fix it?
Upvotes: 3
Views: 259
Reputation: 33092
Why is this not working and how should I fix it?
In order to work if constexpr
(i.e. discard the false statement at compile time), you need to make it template depended.
From cppreference.com, under the if constexpr
section:
Outside a template, a discarded statement is fully checked.
if constexpr
is not a substitute for the#if
preprocessing directive:void f() { if constexpr(false) { int i = 0; int *p = i; // Error even though in discarded statement } }
Therefore, the fix is to wrap the statement into a template function, as follows:
template<typename T1, typename T2> auto func()
{
if constexpr (HasFriction<T1, T2>::value) {
MyStruct<A, C> f;
return f.value;
}
else {
MyStruct<A, C> no_f;
return 0;
}
}
Now in main()
func<A, B>();
Upvotes: 5