Аргументи за замовчуванням шаблону


151

Якщо мені дозволено робити наступне:

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

Чому в основному мені не дозволяють робити наступне?

Foo me;

Але я повинен вказати наступне:

Foo<int> me;

C ++ 11 представив аргументи шаблону за замовчуванням і зараз вони невловимі для мого повного розуміння.

Відповіді:


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.
Силікоманс

1
@Silicomancer Важко сказати, не бачачи свого коду та командного рядка ... Можливо, ти маєш справу з вказівниками, як тут ?
Паоло М

1
Кланг не приймає, здається? coliru.stacked-crooked.com/a/c5d3c0f90ed263c2
Borgleader

1
@Borgleader Мабуть, Coliru використовує кланг 5.0. Судячи з цього , він повинен підтримувати виведення аргументів шаблону C ++ 17, але, очевидно, ідентифікатор цього не робить. Якщо ви спробуєте свій самий приклад у wandbox, використовуючи кланг 7.0, він працює бездоганно.
Паоло М

2
@ PaoloM О, круто, радий дізнатися, що це просто проблема версії компілятора. Дякуємо, що вивчили це.
Боргледер

19

Вам не дозволяється це робити, але ви можете це зробити

typedef Foo<> Fooo;

а потім робити

Fooo me;

Чи є різниця в цьому з типом за замовчуванням і: typedef Foo<float> Fooo;без типу за замовчуванням?
qrikko

5
С ++ 11-іш способом було б сказатиusing Fooo = Foo<>;
Адріан Ш

18

Ви можете використовувати наступне:

Foo<> me;

І intбудьте аргументом вашого шаблону. Кутові дужки необхідні і їх не можна опустити.


Має сенс і дякую, але, як зазначено нижче, чому специфіки типу мають бути присутніми?
користувач633658

@ user633658: Ви мали на увазі "специфікатор типу"? Я не впевнений, що розумію
Енді Проул

У будь-якому разі, що стосується необхідності порожніх кутових дужок, я можу робити лише підказки, і всі вони стосуються виключення можливих неоднозначностей із використанням лише імені шаблону, але я мушу визнати, що я не знаю точно причина
Енді Проул

Я сильно підозрюю, що вимога <> полягає в тому, щоб дозволити аналізатору компілятора визначити, що ви посилаєтесь на шаблонний клас під назвою foo, а не на щось інше, що називається foo.
Мак
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.