Search code examples
c++assert

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?


Solution

  • 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.