Tamás Szelei
Tamás Szelei

Reputation: 23931

Can I perform an optional static_assert if the parameter is known at compile time?

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

Answers (2)

Pumkko
Pumkko

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

Hatted Rooster
Hatted Rooster

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

Related Questions