Wie kann ich eine C ++ - Vorlagenklasse weiterleiten?

98

Bei einer Vorlagenklasse wie der folgenden:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

Wie kann jemand diese Klasse in einer Header-Datei weiterleiten?

Tron Thomas
quelle

Antworten:

102

So würden Sie es machen:

template<typename Type, typename IDType=typename Type::IDType>
class Mappings;

template<typename Type, typename IDType>
class Mappings
{
public:
    ...
    Type valueFor(const IDType& id) { // return value }
    ...
};

Beachten Sie, dass der Standard in der Vorwärtsdeklaration und nicht in der tatsächlichen Definition enthalten ist.

Pubby
quelle
Es ist möglich, eine Klasse weiterzuleiten, deren Standardwerte in ihrer Definition aufgeführt sind. Siehe meine Antwort.
Elliott
Ich bin nicht einverstanden. Der Standard sagt: „Ein Template-Parameter werden nicht Standardargumente durch zwei verschiedene Erklärungen im gleichen Umfang gegeben werden“ . Und ich habe nur in der ersten Erklärung nichts über Standardeinstellungen gefunden. Auch der Code mit der Vorwärtsdeklaration und den Standardwerten in der Definition wird erfolgreich kompiliert und ausgeführt. Sind Sie sicher, was Sie behaupten? Können Sie ein Angebot aus dem Standard machen?
Oleksij Plotnyc'kyj
@ Elliott Es scheint, dass es wahr ist. Der Standard [17.1.9] lautet: "In einer Vorlagendeklaration kann ein Standardvorlagenargument angegeben werden." Muss nicht sein, darf aber sein. Daher verstehe ich nicht, warum andere Antworten behaupten, dass es in der ersten Erklärung sein sollte.
Oleksij Plotnyc'kyj
Und es scheint viel bequemer zu sein, Standardeinstellungen in der Definition zu haben.
Oleksij Plotnyc'kyj
8

Sie können Standardargumente für eine Vorlage nur für die erste Deklaration der Vorlage deklarieren. Wenn Sie Benutzern erlauben möchten, eine Klassenvorlage weiterzuleiten, sollten Sie einen Weiterleitungsheader bereitstellen. Wenn Sie die Klassenvorlage eines anderen anhand der Standardeinstellungen weiterleiten möchten, haben Sie kein Glück!

Dietmar Kühl
quelle
Es ist möglich, eine Klasse weiterzuleiten, deren Standardwerte in ihrer Definition aufgeführt sind. Siehe meine Antwort.
Elliott
Ich bin nicht einverstanden. Der Standard sagt: „Ein Template-Parameter werden nicht Standardargumente durch zwei verschiedene Erklärungen im gleichen Umfang gegeben werden“ . Und ich habe nur in der ersten Erklärung nichts über Standardeinstellungen gefunden. Auch der Code mit der Vorwärtsdeklaration und den Standardwerten in der Definition wird erfolgreich kompiliert und ausgeführt. Sind Sie sicher, was Sie behaupten? Können Sie ein Angebot aus dem Standard machen?
Oleksij Plotnyc'kyj
3

Sie können eine Vorlagenklasse deklarieren, deren Definition die Standardargumente angibt. Jedes Mal, wenn Sie auf die Klasse verweisen, müssen Sie jedoch alle Argumente einschließen, bis die Definition eingeführt wird.

z.B. Lassen Sie uns verwenden, std::vectorohne es einzuschließen (das zweite Argument von std::vectorist mit einem Standard definiert):

namespace std
{
    template<typename, typename>
    class vector;
}

#include <iostream>

template <typename S, typename T>
void Foo (const std::vector<S,T> & vector)
{
    std::cout << "do vector stuff, eg., display size = "
        << vector.size() << std::endl;
}

template <typename T>
void Foo (const T & t)
{
    std::cout << "do non-vector stuff..." << std::endl;
}

Wir können es dann verwenden, ohne den Vektor einzuschließen, z.

int main()
{
    Foo(3);
}

Und wir können es verwenden mit std::vector zB:

#include <vector>

// Now the compiler understands how to handle
// std::vector with one argument
// (making use of its default argument)

int main()
{
    Foo(std::vector<int>(3));
}

Ich habe überprüft nicht die Standards, aber das funktioniert auf clang/ gccmit -std=c++98bis zu -std=c++17, so dass , wenn es nicht offiziell ein Standard ist , dann sieht es inoffiziell so sein.

Elliott
quelle
Vielleicht vergessen Sie leere spitze Klammern Foo<> foo;.
Oleksij Plotnyc'kyj
@ OleksijPlotnyc'kyj du hast recht. Vielen Dank. Ich habe diesen Zusatz gelöscht.
Elliott