Ich möchte so etwas schreiben:Iterate mit constexpr
template<int i> void f() {}
for (constexpr int i : {1,2,3})
{
f<i>();
}
Ist es möglich, auf constexpr iterieren?
Danke
Ich möchte so etwas schreiben:Iterate mit constexpr
template<int i> void f() {}
for (constexpr int i : {1,2,3})
{
f<i>();
}
Ist es möglich, auf constexpr iterieren?
Danke
Wie Sie wahrscheinlich verstehen, können Sie das nicht tun, wie von:
for (constexpr int i : {1,2,3})
{
f<i>();
}
denn wenn i
eine Zahl von 1 bis 3 in einer Schleife variieren, dann ist es eine Variable und kein compiletime Konstante. Und eine Variable kann kein Template-Argument sein, wie in f<i>
: nur eine Compiletime-Konstante kann ein Template-Argument sein.
In C++ 11 und später dank variadic templates, Sie können effektiv eine willkürliche Folge von compiletime iterieren Konstanten durch compiletime Rekursion einer Template-Funktion verwenden, das eine geeignete beliebige Reihenfolge von Template-Argumenten akzeptiert.
Das wird Ihnen kaum etwas bedeuten, wenn Sie nicht bereits wissen, wie es geht. Hier ist ein C 11 ++ Beispiel das tut, was Sie wollen zum Ausdruck bringen:
#include <type_traits>
#include <iostream>
template<int i> void f()
{
std::cout << i << '\n';
}
// This overload is chosen when there is only 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) == 0>::type
for_each_f()
{
f<First>();
}
// This overload is chosen when there is > 1 template argument.
template<int First, int ...Rest>
typename std::enable_if<sizeof...(Rest) != 0>::type
for_each_f()
{
f<First>();
for_each_f<Rest...>();
}
int main()
{
for_each_f<2,3,5,7,11>();
return 0;
}
Neben variadische Vorlagen hängt diese Technik auf dem sehr wichtigen C++ Meta-Programmierung Prinzip der SFINAE und auf std::enable_if
, das ist das Werkzeug, das die Standard-C++ - Bibliothek zum Ausnutzen von SFINAE bietet.
101010 Antwort zeigt einen differenzierteres und kraftvollen Stil von Lösung, die in C++ 14 (und leicht genug, um implementieren, in C++ 11 , wenn Sie etwas Unterstützung vorformulierten schreiben) zur Verfügung steht.
Nein, Sie nicht ein for-Schleife zu durchlaufen bei der Kompilierung verwenden können. Die für die Kontrollstruktur in C++ wird für den Laufzeitkontrollfluss verwendet.
Sie können jedoch auch andere Kompilierzeitfunktionen verwenden. Zum Beispiel in C++ 14 könnten Sie erreichen, was Sie in der folgenden Art und Weise wollen:
eine Vorlage-Wrapper-Klasse definieren, die Ihre Funktion geht zu nennen ist.
template<int i> struct wrapper { void operator()() const { f<i>(); } };
Verwenden std::index_sequence erzeugen Zeitindizes kompilieren.
template<template<int> class W, std::size_t... I> void caller_impl(std::index_sequence<I...>) { int t[] = { 0, ((void)W<I>()(), 1)... }; (void) t; } template<template<int> class W, std::size_t N, typename Indices = std::make_index_sequence<N>> void call_times() { caller_impl<W>(Indices()); }
Dann rufen als
int main() { call_times<wrapper, 42>(); }
Wenn C++ 14 keine Option ist, dass Sie einen Blick darauf werfen konnte here von, wie Sie std::index_sequence
Ihr Selbst implementieren könnten.
Was ist '(void) t' für? –
@DeanSeo unterdrückt Compiler-Warnung für nicht verwendete Variable. – 101010
Wenn Sie C++ 17 haben, dann kann der 'caller_impl' Funktionskörper sein' (W ()(), ...); 'Viel einfacher zu verstehen. –
TBH Ich bevorzuge diesen Ansatz. Um diese Initialisierung von 'int t []' (C++ 's Fehler, nicht 101010) herum gibt es so viel schrecklichen Hacker, dass mir eine Menge Geld gegeben werden müsste, bevor ich diesen Weg gehen würde! –
können Sie die 'enable_if's loswerden, wenn Sie die Template-Signaturen in' template for_each_f(); 'und' template for_each_f(); 'ändern –