Frage

Ist es möglich, einen Vorlagenparameter von Nicht-Typen aus einem Vorlagenfunktionsparameter abzuleiten?

Betrachten Sie diese einfache Vorlage:

template <int N> constexpr int factorial()
{
        return N * factorial<N - 1>();
}

template <> constexpr int factorial<0>()
{
        return 1;
}

template <> constexpr int factorial<1>()
{
        return 1;
}

Ich möchte mich ändern können factorial Damit ich es alternativ so nennen kann:

factorial(5);

und lassen Sie den Compiler den Wert von N zur Kompilierungszeit ermitteln. Ist das möglich? Vielleicht mit einem ausgefallenen C ++ 11 -Zusatz?

War es hilfreich?

Lösung

Kann nicht erledigt werden, es sei denn, Sie haben eine Zeitmaschine.

Der Parameter für die Funktion wird zur Laufzeit behandelt. Ja in dein Fall ist es eine wörtliche Konstante, aber das ist ein Sonderfall.

In Funktionsdefinitionen der Parameter Typen werden bei Compile-Zeit festgelegt (und kann daher verwendet werden, um Vorlagenparameter abzuleiten), aber Parameter Werte werden nur zur Laufzeit befestigt.

Warum brauchst du das? Ist es nur so, dass Sie das nicht eingeben müssen <>'s?

Andere Tipps

Ihr aktueller Code würde normalerweise wie folgt geschrieben, glaube ich:

constexpr factorial (int n)
{
    return n > 0 ? n * factorial( n - 1 ) : 1;
}

Wenn Sie es mit einer konstanten Expression nennen, z. factorial(5), Dann wird die gesamte Compiler -Magie ins Spiel kommen. Aber wenn du das tust int a = 3; factorial(a), Dann denke ich, dass es auf eine herkömmliche Funktion zurückgreifen wird - dh es hat keine Nachschlagtabelle mit vorbereiteten Antworten aufgebaut.

Im Allgemeinen sollten Sie jede Funktion und jeden Konstruktor als markieren constexpr falls Sie können. Sie verlieren nichts, der Compiler wird es bei Bedarf als normale Funktion behandeln.

Ich glaube nicht, dass Sie das tun können. Der einzige Weg, wie Sie das tun könnten, wäre eine constexpr Funktionsparameter, der dann als die übergeben würde als die template Parameter für die Vorlagenversion von factorial, aber constexpr Funktionsparameter werden nicht zugelassen.

Nein, es ist nicht möglich, es sei denn, Sie möchten eine riesige Switch -Anweisung erstellen:

int getFactorial( const int v )
{
  switch ( v )
  {
    case 1 : return factorial<1>();
    case 2 : return factorial<2>();
    //etc
    default:
       ;
  }
  return 0;
}

Nein, das kannst du nicht. Vorlagenargumente können nur aus dem abgeleitet werden Typ des Funktionsarguments, nicht das Wert, was im Allgemeinen nicht zur Kompilierungszeit bekannt sein wird.

Natürlich könntest du neu schreiben factorial als Nicht-Template constexpr Funktion; Dann würde es zum Kompilierungszeit bewertet, wenn das Argument dann bekannt ist.

Verwenden Sie ein böses Makro:

#define factorial(X) factorial<X>()
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top