web-dev-qa-db-fra.com

La métaprogrammation avec état est-elle (encore) mal formée?

L'une de mes inventions les plus aimées/les plus mauvaises que j'ai eu la chance de rencontrer est le compteur constexpr , alias métaprogrammation avec état. Comme mentionné dans l'article, il semble être légal sous C++ 14, et je me demande si quelque chose a changé avec C++ 17?

Ce qui suit est une mise en œuvre largement basée sur le poste

template <int N>
struct flag
{
    friend constexpr int adl_flag(flag<N>);
    constexpr operator int() { return N; }
};

template <int N>
struct write
{
    friend constexpr int adl_flag(flag<N>) { return N; }
    static constexpr int value = N;
};

template <int N, int = adl_flag(flag<N>{})>
constexpr int read(int, flag<N>, int R = read(0, flag<N + 1>{}))
{
    return R;
}

template <int N>
constexpr int read(float, flag<N>)
{
    return N;
}

template <int N = 0>
constexpr int counter(int R = write<read(0, flag<0>{}) + N>::value)
{
    return R;
}

Et nous tilisez-le comme

static_assert(counter() != counter(), "Your compiler is mad at you"); 

template<int = counter()>
struct S {};

static_assert(!std::is_same_v<S<>, S<>>, "This is ridiculous");

Soit dit en passant, est une contradiction directe avec Stockage des États dans la métaprogrammation C++?

47
Passer By

C'est CWG numéro 2118 actif :

Définir une fonction ami dans un modèle, puis référencer cette fonction plus tard fournit un moyen de capturer et de récupérer l'état de métaprogrammation. Cette technique est mystérieuse et devrait être mal formée.

Notes de la réunion de mai 2015:

Le CWG a convenu que ces techniques devraient être mal formées, bien que le mécanisme pour les interdire soit encore indéterminé.

C'est toujours un problème actif, rien ne changera en C++ 17 au moins pour l'instant. Bien que lorsqu'un tel mécanisme d'interdiction soit déterminé, il puisse être décrété rétroactivement comme un DR.

40
Barry