Como encaminhar declarar uma classe de modelo C ++?

99

Dada uma classe de modelo como a seguinte:

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

Como alguém pode declarar essa classe em um arquivo de cabeçalho?

Tron Thomas
fonte

Respostas:

103

É assim que você faria:

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

Observe que o padrão está na declaração de encaminhamento e não na definição real.

Pubby
fonte
É possível declarar progressivamente uma classe que tem seus padrões listados em sua definição. Veja minha resposta.
Elliott
Discordo. O padrão diz: "Um parâmetro-modelo não deve receber argumentos padrão por duas declarações diferentes no mesmo escopo" . E não encontrei nada sobre padrões apenas na primeira declaração. Além disso, o código com a declaração de encaminhamento e padrões na definição é compilado e executado com êxito. Tem certeza do que está reivindicando? Você pode fornecer uma cotação do padrão?
olek stolar
@Elliott Parece que é verdade. O padrão [17.1.9] diz: "Um argumento-modelo padrão pode ser especificado em uma declaração de modelo." Não deve ser, mas pode ser. Portanto, não entendo por que outras respostas afirmam que deveria estar na primeira declaração.
olek stolar
E parece ser muito mais conveniente ter padrões na definição.
olek stolar
8

Você pode declarar argumentos padrão para um modelo apenas para a primeira declaração do modelo. Se você deseja permitir que os usuários declarem um modelo de classe, você deve fornecer um cabeçalho de encaminhamento. Se você deseja declarar o template de classe de outra pessoa usando padrões, você está sem sorte!

Dietmar Kühl
fonte
É possível declarar progressivamente uma classe que tem seus padrões listados em sua definição. Veja minha resposta.
Elliott
Discordo. O padrão diz: "Um parâmetro-modelo não deve receber argumentos padrão por duas declarações diferentes no mesmo escopo" . E não encontrei nada sobre padrões apenas na primeira declaração. Além disso, o código com a declaração de encaminhamento e padrões na definição é compilado e executado com êxito. Tem certeza do que está reivindicando? Você pode fornecer uma cotação do padrão?
olek stolar
3

Você pode declarar uma classe modelada cuja definição declara os argumentos padrão, mas sempre que fizer referência à classe, deverá incluir todos os seus argumentos até que a definição seja introduzida.

por exemplo. Vamos usar std::vectorsem incluí-lo (o segundo argumento de std::vectoré definido com um padrão):

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

Podemos então usá-lo sem incluir o vetor, por exemplo:

int main()
{
    Foo(3);
}

E podemos usá-lo com std::vector , por exemplo:

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

Não verifiquei os padrões, mas isso funciona em clang/ gcccom -std=c++98até -std=c++17, então, se não for oficialmente um padrão, parece que não é oficial.

Elliott
fonte
Talvez você esqueça os colchetes angulares vazios Foo<> foo;.
olek stolar de
@ OleksijPlotnyc'kyj você está certo. Obrigado. Excluí essa adição.
Elliott