Eine meiner geliebtesten/bösartigsten Erfindungen, auf die ich das Glück hatte, zu stoßen, ist die constexpr-Zähler, auch bekannt als zustandsbehaftete Metaprogrammierung. Wie im Beitrag erwähnt, scheint es unter C ++ 14 legal zu sein, und ich frage mich, ob sich mit C ++ 17 etwas geändert hat.
Das Folgende ist eine Implementierung, die weitgehend auf der Post basiert
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;
}
Und wir benutze es als
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");
Ist dies übrigens ein direkter Widerspruch zum Speichern von Zuständen in der C++-Metaprogrammierung?
Wie funktioniert
read(0, flag<N + 1>{})
führt nicht zu einer Endlosschleife? Das Literal 0 bewirkt, dass die erste Überladung aufgerufen wird (int
gegenüber bevorzugt werdenfloat
), die es natürlich immer und immer wieder aufrufen wird. Was ist die Beendigungsbedingung?– Nicol Bolas
30. Mai 2017 um 16:56 Uhr
@NicolBolas Von SFINAE, der
int
Überlastung vonread(0, flag<N + 1>{})
kann nicht für einige groß genug aufgerufen werdenN
da wir noch nicht definiert habenadl_flag(flag<N + 1>)
deshalb, diefloat
Überladung würde aufgerufen werden. Für die vollständige Erklärung ist der verlinkte Beitrag hervorragend geschrieben.– Passant
30. Mai 2017 um 16:58 Uhr
Beachten Sie auch die Mängel, auf die David Krauss im entsprechenden hinwies std-Diskussion Thread, den Filip versprochen hat, in einem vierten Beitrag anzusprechen, es aber nie getan hat.
– Kolumbus
30. Mai 2017 um 17:30 Uhr
Das ist schrecklich, ich liebe es!
– Mark K. Cowan
30. Mai 2017 um 23:50 Uhr
Muss der Compiler tatsächlich jedes Mal, wenn die Vorlage verwendet wird, einen Standardvorlagenparameter neu auswerten (ohne diesen Parameter anzugeben)?
– Gebührensumme
31. Mai 2017 um 16:24 Uhr