10 Stimmen

Wie kann man die teilweise Spezialisierung einer Funktionsvorlage umgehen?

Zum Beispiel habe ich eine Klasse:

class A
{
    enum {N = 5};
    double mVariable;

    template
    void f(T& t)
    {
        g(mVariable); // Aufruf einer Funktion unter Verwendung von mVariable.
        f(t); // Gehe zur nächsten Schleife
    }

    template
    void f(T& t)
    {} // Stoppe die Schleife, wenn N erreicht ist.
};

Teilspezialisierung ist in Funktionstemplates nicht erlaubt. Wie umgehe ich es in meinem Fall?

Ich habe das Beispiel von Arne Mertz leicht geändert, wie:

template
struct A
{
    enum {N = n};
    ...
};

und verwende A wie:

A<5> a;

Ich kann nicht auf Visual Studio 2012 kompilieren. Handelt es sich um einen Compilerfehler oder etwas anderes? Es ist ziemlich seltsam.

EDIT: Überprüft. Es handelt sich um einen Visual Studio-Bug. :(

Ich denke, Nim bietet den einfachsten Weg, um es zu implementieren.

7voto

Arne Mertz Punkte 23412

Die einfachste Lösung besteht darin, anstelle einer Funktion eine Template-Klasse zu verwenden:

class A
{
    enum {N = 5};
    double mVariable;

    template 
    struct fImpl {
      static_assert(i::call(t, a);
      }
    };

    template
    struct fImpl {
      static void call(T&, A&)  {} // Schleife beenden, wenn N erreicht wird.
    };

 public:

    template
    void f(T& t)
    {
        fImpl::call(t,*this);
    }

};

Beispiel-Link

4voto

Sie können eine Hilfsklasse definieren:

template 
struct inc_up_to
{
  static const int value = i + 1;
};

template 
struct inc_up_to
{
  static const int value = i;
};

template
void f(T& t)
{
    if (i < N) {
        g(mVariable); // rufen Sie eine Funktion auf, die mVariable verwendet.
        f::value>(t);
    }
}

Es stoppt die Kompilierzeit-Rekursion, indem f auf f verweist, aber dieser Aufruf wird durch die Laufzeitbedingung vermieden, was die Schleife unterbricht.

Eine vereinfachte und robustere Version des Helfers (danke @ArneMertz) ist auch möglich:

template 
struct inc_up_to
{
  static const int value = (i >= M ? M : i + 1); // das kapselt bei M
  // oder dies:
  static const int value = (i >= M ? i : i + 1); // das lässt i >= M unverändert
};

Dies erfordert noch nicht einmal die teilweise Spezialisierung.

2voto

Nim Punkte 32693

Mit c++11-Unterstützung können Sie Folgendes tun:

#include 
#include 
using namespace std;

struct A
{
    enum {N = 5};
    double mVariable;

    void g(int i, double v)
    { std::cout << i << "  " << v << std::endl; }

    template
    typename enable_if= N>::type f(T& t)
    {} // stop loop when hit N.

    template
    typename enable_if::type f(T& t)
    {
        g(i, mVariable); // call some function using mVariable.
        f(t); // go to next loop
    }

};

int main(void)
{
    A a;
    int v = 0;
    a.f<0>(v);
}

__

Der Hauptgrund, warum ich es mag, ist, dass Sie keinen der Überbleibsel benötigen, wie sie in den vorherigen Antworten erforderlich waren...

__

2voto

Constructor Punkte 7293

Sie können die teilweise Spezialisierung eines Funktionsvorlagetemplates mit Funktionsüberladung nachahmen:

#include 

class A
{
    enum {N = 5};
    double mVariable;

    // ...

    void g(double)
    {
        // ...
    }

public:

    template
    void f(T& t, std::integral_constant = std::integral_constant())
    {
        g(mVariable);
        f(t, std::integral_constant());
    }

    template
    void f(T& t, std::integral_constant)
    {
    }

};

Beispiel für die Verwendung:

A a;
int t = 0;

a.f(t);
a.f(t, std::integral_constant()); // wenn Sie die Schleife ab 2 starten möchten, nicht ab 0

Es handelt sich um eine C++11-Lösung, jedoch nicht so sehr wegen der Klasse std::integral_constant, sonderm wegen des Standardtemplateparameters des Funktionsvorlagetemplates. Es kann kürzer gemacht werden, indem einige zusätzliche C++11-Funktionen verwendet werden:

template
using integer = std::integral_constant;

template
void f(T& t, integer = {})
{
    g(mVariable);
    f(t, integer());
}

template
void f(T& t, integer)
{
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X