Reputation: 1817
let's say I have an enumeration:
typedef enum {
Val1,
Val2,
Val3,
Val4
} vals;
And a function check(vals x)
which returns a boolean indicating whether the val is in a specific subset of values in vals
.
bool check(vals x) {
switch(x) {
case Val1:
case Val3:
return true;
}
return false;
}
I want to use this function as a condition for the enable_if
(the function, as you can see, it's not a function depending on the runtime), to let the users use only those values with the class template.
class MyClass<vals v> {
}
PS: I need the template to make specializations for a method of the class, depending on the template value.
Upvotes: 4
Views: 196
Reputation: 1817
Thanks for the answer guys. I found another solution that could be even better for my problem. Since I have to implement a specialized method for all of the supported values, I can even put an assertion in the unspecialized method.
template<vals v>
MyClass<v>::method() {
assert(check(v) && "Unsupported value!");
}
template<>
MyClass<Val1>::method() {
// do it!
}
Upvotes: 0
Reputation: 50568
You don't need neither a function nor enable_if
to do that.
Here is an example:
enum class vals {
Val1,
Val2,
Val3,
Val4
};
template<vals v, bool = (v == vals::Val1 || v == vals::Val3)>
class MyClass;
template<vals v>
class MyClass<v, true> { };
int main() {
MyClass<vals::Val1> ok;
// MyClass<vals::Val2> ko;
}
This solution has actually a problem: MyClass<vals::Val2, true> ok;
is a valid statement.
Anyway, if it fits well mostly depends on the real problem.
If you want to use enable_if
you can do this:
#include<type_traits>
enum class vals {
Val1,
Val2,
Val3,
Val4
};
template<vals v, std::enable_if_t<(v == vals::Val1 || v == vals::Val3)>* = nullptr>
class MyClass { };
int main() {
MyClass<vals::Val1> ok;
// MyClass<vals::Val2> ko;
}
Another solution would be using a static_assert
:
enum class vals {
Val1,
Val2,
Val3,
Val4
};
template<vals v>
class MyClass {
static_assert((v == vals::Val1 || v == vals::Val3), "!");
};
int main() {
MyClass<vals::Val1> ok;
// MyClass<vals::Val2> ko;
}
And so on, there exist a bunch of alternatives that does not require a constexpr
ed function.
Otherwise let the function be constexpr
as mentioned by @n.m. and that's all.
Upvotes: 4
Reputation: 120089
In C++14, just declare the function constexpr
and keep the implementation as is.
In C+11 you need to change it to a single return statement:
constexpr bool check(vals x) {
return x == Val1 || x == Val3;
}
Upvotes: 6