Як переслати оголошення класу шаблону C ++?


101

Дано клас шаблону, такий як:

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

Як хтось вперед може оголосити цей клас у файлі заголовка?

Відповіді:


104

Ось як би ви це зробили:

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

Зверніть увагу, що за замовчуванням декларація пересилає, а не фактичне визначення.


Можна переадресувати декларування класу, значення якого за замовчуванням перелічено у його визначенні. Дивіться мою відповідь.
Елліот

Я не погоджуюсь. Стандарт говорить: "Шаблон-параметр не повинен отримувати аргументи за замовчуванням двома різними оголошеннями в одній області" . І я не знайшов нічого про дефолти лише у першій декларації. Також успішно компілюється та запускається код із прямою декларацією та за замовчуванням у визначенні. Ви впевнені у тому, що заявляєте? Чи можете ви навести цитату зі стандарту?
olek stolar

@Elliott Здається, це правда. Стандарт [17.1.9] говорить: "Шаблон-аргумент за замовчуванням може бути вказаний у декларації шаблону." Не повинно бути, але може бути. Таким чином, я не розумію, чому інші відповіді стверджують, що це повинно бути в першій декларації.
olek stolar

І здається, набагато зручніше мати значення за замовчуванням у визначенні.
olek stolar

8

Ви можете оголосити аргументи за замовчуванням для шаблону лише для першого оголошення шаблону. Якщо ви хочете дозволити користувачам переадресувати оголошення класу шаблону, вам слід надати заголовок переадресації. Якщо ви хочете переслати декларувати шаблон іншого класу за замовчуванням, вам не пощастило!


Можна переадресувати декларування класу, значення якого за замовчуванням перелічено у його визначенні. Дивіться мою відповідь.
Елліот

Я не погоджуюсь. Стандарт говорить: "Шаблон-параметр не повинен отримувати аргументи за замовчуванням двома різними оголошеннями в одній області" . І я не знайшов нічого про дефолти лише у першій декларації. Також успішно компілюється та запускається код із прямою декларацією та за замовчуванням у визначенні. Ви впевнені у тому, що заявляєте? Чи можете ви навести цитату зі стандарту?
olek stolar

3

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

напр. Давайте використовувати, 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;.
olek stolar

@ OleksijPlotnyc'kyj ти маєш рацію. Дякую. Я видалив це доповнення.
Елліот,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.