2 votes

is_constant_evaluated() devrait produire des variables constexpr ?

J'ai lu le std::is_constant_evaluated() mais je ne sais toujours pas pourquoi (1) ne fonctionne pas avec la définition de la dernier CCG : error: 'x' is not a constant expression

template<auto v>
struct s
{};

constexpr void f(int x)
{
    if (std::is_constant_evaluated())
    {
        // constexpr int z=x; (1)
        // s<x> a; (2)
    }
}

int main(int argc, char* argv[])
{
    f(4);
    //f(argc);
    return 0;
}
  1. Selon la norme, cela devrait-il fonctionner ?
  2. Ou simplement l'implémentation de GCC est boguée ?
  3. Comment puis-je obtenir le comportement attendu ? Ce qui est en gros :

Avec un branchement sur std::is_constant_evaluated()

  • si c'est vrai : le code peut utiliser les variables comme constexpr (comme (2))
  • si c'est faux : le code utilise les variables comme des non-constexpr.

UPDATE

Puis-je "transporter" l'information sur la constexprésence dans une fonction ? Il s'agit essentiellement de décider dans f() qu'il a été appelé avec constexpr x ou non.

UPDATE Un exemple plus complexe de ce que j'aimerais réaliser : cet échantillon devrait, si possible, stringifier le paramètre au moment de la compilation.

template<auto v>
struct dummy_stringify
{
    static constexpr auto str=v==4 ? "4" : "31"; // this is just an example; imagine here a much more complex logic
};

constexpr void f(int x)
{
    if (std::is_constant_evaluated())
    {
        std::puts("A compile time calculation:");
        //std::puts(dummy_stringify<x>::str);
    } else
    {
        std::cout<<"A runtime calculation:"<<std::endl;
        std::cout<<x<<std::endl;
    }
}
int main(int argc, char* argv[])
{
    f(4);
    f(argc);
    return 0;
}

7voto

StoryTeller Points 6139

x n'est pas une expression constante, peu importe comment f lui-même est évalué. Il s'agit d'une if juste là (comment is_constant_evaluated est destiné à être utilisé). Il ne s'agit pas d'une branche rejetée, elle doit donc contenir du code bien formé même lorsque f es no constante évaluée. Lorsque x ne sera pas une expression constante, la fonction contiendra toujours cette branche (non exécutée), et elle tentera d'utiliser la fonction x où une expression constante est nécessaire. C'est tout simplement mal formé.

Le CCG a tout à fait raison de ne pas l'accepter.

3voto

Davis Herring Points 7254

La question fondamentale ici est que, même avec une constexpr (ou même consteval ) appelée pendant l'évaluation d'une constante (et sous une fonction is_constant_evaluated ), il n'y a toujours que un fonction partagée entre toutes les valeurs des arguments. Vous ne pouvez donc pas jamais utiliser un paramètre de fonction en tant qu'expression constante (même si la fonction appelez avec ce paramètre est une expression constante). Si vous voulez un paramètre d'expression constante, il doit être un modèle paramètre.

0voto

Balázs Árva Points 143

UPDATE

J'ai trouvé une solution avec une petite classe d'aide (bien sûr on peut utiliser std::integral_constant )

template<auto val_>
struct val
{
    static constexpr auto value=val_;
};

template<auto v>
struct dummy_stringify
{
    static constexpr auto str=v==4 ? "4" : "31"; // this is just an example; imagine here a much more complex logic
};

#include <iostream>
using namespace std;

template<class T>
constexpr void f(T x)
{
    if constexpr(requires{ T::value; })
    {
        std::puts("A compile time calculation:");
        std::puts(dummy_stringify<T::value>::str);
    } else
    {
        std::cout<<"A runtime calculation:"<<std::endl;
        std::cout<<x<<std::endl;
    }
}
int main(int argc, char* argv[])
{
    f(val<4>{});
    f(argc);
    return 0;
}

Il peut être amélioré avec un template<char...> auto operator""_v(); a f(4_v)

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X