Аргументы шаблона по умолчанию

151

Если мне разрешено делать следующее:

template <typename T = int>
class Foo{
};

Почему мне не разрешено делать следующее в основном?

Foo me;

Но я должен указать следующее:

Foo<int> me;

C ++ 11 представил аргументы шаблона по умолчанию, и сейчас они не совсем понятны.

user633658
источник

Ответы:

188

Ты должен сделать:

Foo<> me;

Аргументы шаблона должны присутствовать, но вы можете оставить их пустыми.

Думайте об этом как о функции fooс единственным аргументом по умолчанию. Выражение fooне будет называть это, но foo()будет. Синтаксис аргумента должен все еще быть там. Это согласуется с этим.

Джозеф Мэнсфилд
источник
4
@Pubby Я предполагаю , что это создало бы ненужные осложнения , если Foo может быть идентификатором шаблона или могут быть явная конкретизацией в зависимости от того, есть ли аргумент по умолчанию. Лучше сохранить явный синтаксис создания экземпляров. Думайте об этом как о функции fooс единственным параметром по умолчанию. Вы не можете назвать это как foo, вы называете это с foo(). Имеет смысл сохранять это последовательным.
Джозеф Мэнсфилд
2
@sftrabbit, но вы не можете вызвать функцию без аргументов, как foo; Вы можете назвать класс без аргументов, как, Fooоднако.
Сет Карнеги
4
@aschepler С функцией аргументы шаблона могут быть выведены из аргументов функции. С классом невозможно решить, подразумеваете ли вы класс шаблона с аргументами по умолчанию или не шаблонный класс.
Олаф Дитче
21
@OlafDietsche, но вы не можете иметь шаблонный класс и не шаблонный класс с одним и тем же именем, поэтому компилятор должен иметь возможность решить, просто посмотрев, как это имя.
Сет Карнеги
7
@Pubby Стандартный комитет спросил себя так же, я думаю. Теперь с C ++ 17 <>в этом случае больше нет необходимости. Проверьте мой ответ для более подробной информации.
Паоло М
53

С C ++ 17 вы действительно можете.

Эта функция называется вычетом аргументов шаблона класса и обеспечивает большую гибкость в способе объявления переменных шаблонных типов .

Так,

template <typename T = int>
class Foo{};

int main() {
    Foo f;
}

теперь допустимый код C ++ .

Паоло М
источник
5
Странный. Просто попробовал это в моем проекте C ++ 17, и он не работал: «за шаблоном-заполнителем типа« const MyType »должен следовать простой идентификатор объявления». Я использую GCC 7.3.0.
Silicomancer
1
@ Silicomancer Трудно сказать, не видя ваш код и командную строку ... Может быть, вы имеете дело с указателями, как здесь ?
Паоло М
1
Clang не принимает это кажется? coliru.stacked-crooked.com/a/c5d3c0f90ed263c2
Borgleader
1
@ Borgleader Видимо, Coliru использует Clang 5.0. Судя по этому , он должен поддерживать вывод аргументов шаблона C ++ 17, но, очевидно, id - нет. Если вы попробуете тот же самый пример в wandbox, используя clang 7.0, он будет работать безупречно.
Paolo M
2
@PaoloM О, круто, рад знать, что это просто проблема версии компилятора. Спасибо, что заглянули в это.
Borgleader
19

Вам не разрешено делать это, но вы можете сделать это

typedef Foo<> Fooo;

а затем сделать

Fooo me;
g24l
источник
Есть ли разница в этом с типом по умолчанию и:, typedef Foo<float> Fooo;без типа по умолчанию?
qrikko
5
C + + 11-й способ был бы сказатьusing Fooo = Foo<>;
Adrian W
18

Вы можете использовать следующее:

Foo<> me;

И должен intбыть вашим аргументом шаблона. Угловые скобки необходимы и не могут быть опущены.

Энди Проул
источник
Имеет смысл и спасибо, но, как отмечено ниже, почему указание типа не должно присутствовать?
user633658
@ user633658: Вы имели в виду «спецификатор типа»? Я не уверен, что понимаю
Энди Prowl
В любом случае, что касается причины, по которой нужны пустые угловые скобки, я могу только делать предположения, и все они связаны с тем, чтобы исключить возможные неясности с использованием только имени шаблона, но я должен признаться, что не знаю точного причина
Энди Prowl
Я сильно подозреваю, что требование для <> должно позволить парсеру компилятора определить, что вы имеете в виду шаблонный класс с именем foo, а не что-то еще с именем foo.
Mac