Search code examples
c++template-meta-programmingconstexprc++20if-constexpr

C++ check if statement can be evaluated constexpr


Is there a method to decide whether something can be constexpr evaluated, and use the result as a constexpr boolean? My simplified use case is as follows:

template <typename base>
class derived
{
    template<size_t size>
    void do_stuff() { (...) }
    
    void do_stuff(size_t size) { (...) }
public:
    void execute()
    {
        if constexpr(is_constexpr(base::get_data())
        {
            do_stuff<base::get_data()>();
        }
        else
        {
            do_stuff(base::get_data());
        }
    }
};

My target is C++2a.

I found the following reddit thread, but I'm not a big fan of the macros. https://www.reddit.com/r/cpp/comments/7c208c/is_constexpr_a_macro_that_check_if_an_expression/


Solution

  • Here's another solution, which is more generic (applicable to any expression, without defining a separate template each time).

    This solution leverages that (1) lambda expressions can be constexpr as of C++17 (2) the type of a captureless lambda is default constructible as of C++20.

    The idea is, the overload that returns true is selected when and only when Lambda{}() can appear within a template argument, which effectively requires the lambda invocation to be a constant expression.

    template<class Lambda, int=(Lambda{}(), 0)>
    constexpr bool is_constexpr(Lambda) { return true; }
    constexpr bool is_constexpr(...) { return false; }
    
    template <typename base>
    class derived
    {
        // ...
    
        void execute()
        {
            if constexpr(is_constexpr([]{ base::get_data(); }))
                do_stuff<base::get_data()>();
            else
                do_stuff(base::get_data());
        }
    }