Search code examples
c++c++17constexprif-constexpr

constexpr condition not constant?


I wrote the following C++17 code:

constexpr bool gDebug = true;

template <typename T> constexpr const T& Select(const bool pCondition, const T& a, const T& b)
{
   if constexpr (pCondition)
   {
      return a;
   }
   else
   {
      return b;
   }
}

Then I called it like this:

int c = Select<QString>(gDebug, a, b); // In .cpp

I get error: ‘pCondition’ is not a constant expression for the if constexpr line.

Why? Shouldn't this work?


Solution

  • Why? Shouldn't this work?

    No, it shouldn't. pCondition is not a constant expression. I can see why this might be confusing, since pCondition is const - but the term constant expression refers to it being able to be evaluated at compile time. That is, not const but really constexpr.

    Function parameters are not constant expressions. The fact that you happen to pass a compile-time constant is immaterial, since you could just as easily pass a runtime variable that you read from stdin or something.

    if constexpr requires a constant expression, so you really just want if there. Or, you need to lift the condition to be a constant expression - such as by making it a template parameter:

    template <bool pCondition, typename T>
    constexpr const T& Select(const T& a, const T& b)
    {
       if constexpr (pCondition) // now okay
       {
          return a;
       }
       else
       {
          return b;
       }
    }
    
    int c = Select<qDebug>(a, b);
    

    or you could require that the parameter be a value encoded into a type:

    template <typename Boolean, typename T>
    constexpr const T& Select(Boolean pCondition, const T&, const T&);
    
    constexpr std::true_type qDebug{}; // true_type, not bool = true
    int c = Select(qDebug, a, b);      // okay