Search code examples
c++templatesconstexprtype-traits

Why can't constexpr be used for non-const variables when the function only uses the types?


Maybe the title is not clear, so concretely:

#include <type_traits>

template<typename T>
constexpr int test(T)
{
    return std::is_integral<T>::value;
}

int main()
{
    constexpr int a = test(1); // right
    constexpr int b = test(1.0); // right
    int c = 2;
    constexpr int d = test(c); // ERROR!
    return 0;
}

In fact, the function doesn't use anything but the type of the parameter, which can be determined obviously in the compilation time. So why is that forbidden and is there any way to make constexpr get the value when only the type of parameter is used?

In fact, I hope to let users call the function through parameters directly rather than code like test<decltype(b)>, which is a feasible but not-convenient-to-use way, to check if the types of parameters obey some rules.


Solution

  • Just take T by reference so it doesn't need to read the value:

    template<typename T>
    constexpr int test(T&&)
    {
        return std::is_integral<std::remove_cvref_t<T>>::value;
    }
    

    You can even declare test with consteval, if you want to.

    (Note that stripping cv-qualifiers isn't necessary in this instance; cv-qualified integral types satisfy the std::is_integral trait.)