Как переслать объявление класса шаблона C ++?

105

Учитывая шаблонный класс, подобный следующему:

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

Как кто-то может напрямую объявить этот класс в файле заголовка?

Трон Томас
источник

Ответы:

108

Вот как бы вы это сделали:

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

Обратите внимание, что по умолчанию используется предварительное объявление, а не фактическое определение.

Пабби
источник
Можно переадресовать объявление класса, значения по умолчанию которого указаны в его определении. Смотрите мой ответ.
Elliott
Я не согласен. В стандарте сказано: «Параметр-шаблон не должен получать аргументы по умолчанию в двух разных объявлениях в одной и той же области» . И я ничего не нашел о значениях по умолчанию только в первом объявлении. Также успешно компилируется и запускается код с предварительным объявлением и значениями по умолчанию в определении. Вы уверены в своих претензиях? Вы можете привести цитату из стандарта?
oleksijp
@Elliott Кажется, это правда. Стандарт [17.1.9] говорит: «Аргумент шаблона по умолчанию может быть указан в объявлении шаблона». Не должно быть, но может быть. Таким образом, я не понимаю, почему в других ответах утверждается, что это должно быть в первом объявлении.
oleksijp
И, кажется, гораздо удобнее иметь в определении значения по умолчанию.
oleksijp
8

Вы можете объявить аргументы по умолчанию для шаблона только для первого объявления шаблона. Если вы хотите, чтобы пользователи могли пересылать объявление шаблона класса, вы должны предоставить заголовок пересылки. Если вы хотите переслать объявление чужого шаблона класса с использованием значений по умолчанию, вам не повезло!

Дитмар Кюль
источник
Можно переадресовать объявление класса, значения по умолчанию которого указаны в его определении. Смотрите мой ответ.
Elliott
Я не согласен. В стандарте сказано: «Параметр-шаблон не должен получать аргументы по умолчанию в двух разных объявлениях в одной и той же области» . И я ничего не нашел о значениях по умолчанию только в первом объявлении. Также успешно компилируется и запускается код с предварительным объявлением и значениями по умолчанию в определении. Вы уверены в своих претензиях? Вы можете привести цитату из стандарта?
oleksijp
4

Вы можете объявить шаблонный класс, в определении которого указаны аргументы по умолчанию, но каждый раз, когда вы ссылаетесь на класс, вы должны включать все его аргументы, пока не будет введено определение.

например. Давайте использовать, std::vectorне включая его (второй аргумент std::vectorопределяется по умолчанию):

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

Затем мы можем использовать его без включения вектора, например:

int main ()
{
    Foo(3);
}

... Или мы можем использовать его с std::vector , например .:

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

Я не проверял стандарты, но это работает до clang/ gccс -std=c++98до -std=c++17, поэтому, если это не официально стандарт, то это выглядит неофициально.

Эллиотт
источник
Может, вы забыли пустые угловые скобки Foo<> foo;.
oleksijp