constexpr if mit logischen Operatoren



  • Hallo Forum,

    wie ist denn die korrekte Verwendung von "constexpr if", wenn mehrere Bedingungen mit logischen Operatoren verknüpft sind, von denen nicht alle Compile-Time-Konstanten sind?

    Ein Beispiel:

    template <typename T>
    double f(T i)
    {
       if (std::is_floating_point<T>::value && i > 3)
          return i;
       else
          return 0.0;
    }
    

    Visual Studio 2019 erzeugt folgende Warnung:

    warning C4127:  conditional expression is constant
    message :  consider using 'if constexpr' statement instead
    

    Ist diese Warnung ein Fehler des Compilers?
    Verwende ich stattdessen nämlich "constexpr if"

    template <typename T>
    double f(T i)
    {
       if constexpr (std::is_floating_point<T>::value && i > 3)
          return i;
       else
          return 0.0;
    }
    

    bekomme ich den Fehler

    error C2131:  expression did not evaluate to a constant
    message :  failure was caused by a read of a variable outside its lifetime
    message :  see usage of 'i'
    

    Das ist offensichtlich mit anderen Compilern genauso. Sind logische Operatoren in "constexpr if" nicht erlaubt oder nur wenn alle Operanden Compile-Time-Konstanten sind?

    Man könnte das splitten aber schön ist es dann nicht mehr...

    template <typename T>
    double f(T i)
    {
       if (i > 3)
       {
          if constexpr (std::is_floating_point<T>::value)
             return i;
          else
             return 0.0;
       }
       else
          return 0.0;
    }
    

    Es wäre nett, wenn mir jemand ein paar Hinweise geben könnte, wie das korrekt aussehen sollte oder was hier Best Practice ist. Danke vorab!



  • Ich finde die Warning auch etwas übertrieben. Wenn dann würde ich aber erstmal das "if constexpr" machen und dann erst das normale. Sonst profitierst du ja erst nicht von der Code-Änderung -- abgesehen davon dass die Warning halt nicht mehr kommt.

    template <typename T>
    double f(T i)
    {
        if constexpr (std::is_floating_point<T>::value) // Generiert keinen Code
           if (i > 3) // Generiert nur Code wenn T ein floating point Typ ist
            return i;
    
       return 0;
    }
    

    Sind logische Operatoren in "constexpr if" nicht erlaubt

    Doch, klar.

    oder nur wenn alle Operanden Compile-Time-Konstanten sind?

    Bingo. Kann auch nicht anders sein, da if constexpr komplett zur Compilezeit ausgewertet werden muss.



  • ps: Und natürlich kannst du f selbst gleich const constexpr machen. Was aber mit deiner Frage nix zu tun hat.



  • @hustbaer
    Vielen Dank für die Hinweise!

    @hustbaer sagte in constexpr if mit logischen Operatoren:

    Ich finde die Warning auch etwas übertrieben.

    Das Warning Level ist recht hoch eingestellt, vermutlich erscheinen deswegen einige Warnings übertrieben. Das setzt sich dann auch entsprechend fort. Wenn ich beispielsweise die von dir vorgeschlagene Reihenfolge einhalte, die für mich absolut plausibel ist, ...

    @hustbaer sagte in constexpr if mit logischen Operatoren:

    > template <typename T>
    > double f(T i)
    > {
    >     if constexpr (std::is_floating_point<T>::value) // Generiert keinen Code
    >        if (i > 3) // Generiert nur Code wenn T ein floating point Typ ist
    >         return i;
    > 
    >    return 0;
    > }
    

    ...bekomme ich für den Fall, dass inicht floating point ist und entsprechend kein Code für diesen Block generiert wird, die Warnung:

    warning C4100:  'i': unreferenced formal parameter
    

    Da wird es in meinen Augen dann doch ein wenig widersinnig 🙂 .

    Aber egal, mit der Information kann ich etwas anfangen und mir etwas einfallen lassen.



  • @LennyS Achja ja das ist dann schon ein wenig doof. Kannst du aber auch workarounden indem du nen Cast nach void machst:

    void fun(int i) {
        (void)i; // suppress unreferenced parameter warning
    }
    

Anmelden zum Antworten