Параметры шаблона по умолчанию
Если мне позволено сделать следующее:
template <typename T = int>
class Foo{
};
Почему мне не разрешено делать следующее в основном?
Foo me;
Но я должен указать следующее:
Foo<int> me;
С++ 11 представил аргументы шаблона по умолчанию, и сейчас они неуловимы для моего полного понимания.
Ответы
Ответ 1
Вам нужно сделать:
Foo<> me;
Аргументы шаблона должны присутствовать, но вы можете оставить их пустыми.
Подумайте об этом как о функции foo
с единственным аргументом по умолчанию. Выражение foo
не будет вызывать его, но foo()
будет. Синтаксис аргументов все равно должен присутствовать. Это согласуется с этим.
Ответ 2
С C++ 17 вы действительно можете.
Эта функция называется удержанием аргументов шаблона класса и обеспечивает большую гибкость в способе объявления переменных шаблонных типов.
Так,
template <typename T = int>
class Foo{};
int main() {
Foo f;
}
теперь является юридическим C++ кодом.
Ответ 3
Вы можете использовать следующее:
Foo<> me;
И пусть int
будет вашим аргументом шаблона. Скобки angular необходимы и не могут быть опущены.
Ответ 4
Вам не разрешено это делать, но вы можете сделать это
typedef Foo<> Fooo;
а затем do
Fooo me;
Ответ 5
Я еще не достиг необходимой репутации, чтобы опубликовать это в качестве комментария для Paolo M, поэтому мне придется опубликовать это следующим образом.
Хотя вывод аргументов шаблона класса, представленный в С++ 17, хорошо работает с GCC 8.X и далее, это приводит к ошибке в GCC 7.X при объединении типов данных шаблона по умолчанию и постоянной перегрузки (http://www.cs.technion.ac.il/users/yechiel/c++-faq/const-overloading.html). Рассмотрим следующий пример:
https://wandbox.org/permlink/YoFIUEYNXZ80D6UN
#include<iostream>
template <typename T = int>
class TemplateClass
{
private:
T _variable;
public:
TemplateClass(T variable)
: _variable(variable)
{}
T& Method()
{
std::cout << "Non-constant implementation called" << std::endl;
return _variable;
}
const T& Method() const
{
std::cout << "Constant implementation called" << std::endl;
return _variable;
}
};
int main()
{
TemplateClass<> NonConstObject(1);
TemplateClass<> const ConstObject(1);
TemplateClass const WhatAboutMe(1); //should behave like ConstObject
double test;
test = NonConstObject.Method();
test = ConstObject.Method();
test = WhatAboutMe.Method(); //but behaves like NonConstObject in GCC 7.X
return test;
}
Даже если можно ожидать, что последний экземпляр "WhatAboutMe" будет постоянным объектом, он вызывает непостоянную реализацию "Method". Как следствие, например, операторы могут изменять элементы этого, казалось бы, постоянного объекта. Эта проблема, похоже, решена в более новых версиях GCC.