Come inoltrare dichiarare una classe modello C ++?


99

Data una classe modello come la seguente:

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

Come può qualcuno in avanti dichiarare questa classe in un file di intestazione?

Risposte:


103

Ecco come lo faresti:

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 }
    ...
};

Si noti che il valore predefinito è nella dichiarazione anticipata e non nella definizione effettiva.


È possibile dichiarare in avanti una classe i cui valori predefiniti sono elencati nella sua definizione. Vedi la mia risposta.
— Elliott

Non sono d'accordo. Lo standard dice: "A un parametro-modello non devono essere forniti argomenti di default da due dichiarazioni diverse nello stesso ambito" . E non ho trovato nulla sui valori predefiniti solo nella prima dichiarazione. Anche il codice con la dichiarazione in avanti e le impostazioni predefinite nella definizione viene compilato ed eseguito correttamente. Sei sicuro di ciò che stai rivendicando? Potete fornire un preventivo dallo standard?
— olek stolar

@Elliott Sembra che sia vero. Lo standard [17.1.9] dice: "Un modello-argomento predefinito può essere specificato in una dichiarazione di modello." Non deve essere, ma potrebbe esserlo. Quindi non capisco perché altre risposte affermino che dovrebbe essere nella prima dichiarazione.
— olek stolar

E sembra molto più conveniente avere valori predefiniti nella definizione.
— olek stolar

8

È possibile dichiarare argomenti predefiniti per un modello solo per la prima dichiarazione del modello. Se si desidera consentire agli utenti di inoltrare la dichiarazione di un modello di classe, è necessario fornire un'intestazione di inoltro. Se vuoi inoltrare la dichiarazione del modello di classe di qualcun altro usando i valori predefiniti, sei sfortunato!


È possibile dichiarare in avanti una classe i cui valori predefiniti sono elencati nella sua definizione. Vedi la mia risposta.
— Elliott

Non sono d'accordo. Lo standard dice: "A un parametro-modello non devono essere forniti argomenti di default da due dichiarazioni diverse nello stesso ambito" . E non ho trovato nulla sui valori predefiniti solo nella prima dichiarazione. Anche il codice con la dichiarazione in avanti e le impostazioni predefinite nella definizione viene compilato ed eseguito correttamente. Sei sicuro di ciò che stai rivendicando? Potete fornire un preventivo dallo standard?
— olek stolar

3

È possibile dichiarare una classe basata su modelli la cui definizione indica gli argomenti predefiniti, ma ogni volta che si fa riferimento alla classe è necessario includere tutti i suoi argomenti finché non viene introdotta la definizione.

per esempio. Usiamo std::vectorsenza includerlo (il secondo argomento di std::vectorè definito con un valore predefinito):

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;
}

Possiamo quindi usarlo senza includere il vettore, ad es .:

int main()
{
    Foo(3);
}

E possiamo usarlo con std::vector , ad esempio:

#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));
}

Non ho controllato gli standard, ma funziona fino a clang/ gcccon , quindi se non è ufficialmente uno standard, sembra che lo sia in modo non ufficiale.-std=c++98-std=c++17


Forse dimentichi le parentesi angolari vuote Foo<> foo;.
— olek stolar

@ OleksijPlotnyc'kyj hai ragione. Grazie. Ho cancellato quell'aggiunta.
— Elliott
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.