Reputation: 23931
I have a function that only accepts unsigned integers greater than 0 and has a debug assert to check it:
void foo(unsigned int x) {
assert(x > 0);
}
Is it possible to add a static_assert
here, so that the code still compiles and also accepts parameters that are not compile time constants?
foo(0); // compilation error
foo(1); // fine
foo(get_x_from_user()); // fine
I know I could make x a template parameter, but I would much prefer to keep this style of call: foo(5);
rather than foo<5>();
.
I was thinking there might be a way to pull this off with a custom integer type, but I couldn't get very far on that route. Is there a way to do this?
Upvotes: 1
Views: 563
Reputation: 1593
If you stick to foo(12)
you can't. Because you want the compiler to know the value of a function parameter at compile time. And it's not possible, parameters values are evaluated at runtime. Then it can't be constexpr
and then you can not use it in a static_assert
.
Upvotes: 1
Reputation: 36483
As far as I know, this is not possible without introducing some kind of templating, for example :
template<int T>
class CustomInt
{
public:
static constexpr int value = T;
};
template<int val>
void check(CustomInt<val> /*k*/)
{
static_assert(CustomInt<val>::value > 0, "error!");
check(val);
}
void check(int k)
{
std::cout << "check";
}
int s()
{
volatile int x = 5;
return x;
}
int main() {
check(CustomInt<0>());
check(s());
return 0;
}
This just moves the templating to the custom type though.
Upvotes: 1