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

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

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

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

Foo me;

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

Foo<int> me;

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

Ответ 1

Вам нужно сделать:

Foo<> me;

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

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

Ответ 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.