Избегайте угловых скобок в шаблоне по умолчанию

Если у меня есть класс шаблона с типом шаблона по умолчанию, я должен написать угловые скобки шаблона. Можно ли как-то этого избежать?

Пример:

template <typename T=int>
class tt {
public:
  T get() { return 5; }
};

...

tt<> t;  // how to avoid <>
std::cout << t.get() << std::endl;

До сих пор я делал это с помощью отдельного пространства имен и переобъявления класса:

namespace detail_ {
template <typename T=int>
class tt {
public:
  T get() { return 5; }
};
}

class tt : public detail_::tt {}

...

tt t;
std::cout << t.get() << std::endl;

Проблема в том, что если я хочу использовать класс с другим типом, мне нужно пройти через пространство имен detail_. Есть ли другое решение, которого я еще не видел.


person user1810087    schedule 15.04.2013    source источник
comment
в чем проблема с <>? Наличие допустимых типов tt и tt<Foo> невозможно на самом деле.   -  person Arne Mertz    schedule 15.04.2013
comment
@ArneMertz проблема только в стиле.   -  person user1810087    schedule 15.04.2013
comment
Так в чем проблема с этим стилем? ;-)   -  person Arne Mertz    schedule 15.04.2013


Ответы (3)


Начиная с C++17, из-за выведения аргументов шаблона класса, вещи изменились.

tt и tt<> — это не одно и то же: типы и шаблоны классов были разными и продолжают трактоваться по-разному.

В любом случае, в простых сценариях, подобных тому, что в вашем примере, С++ 17 предполагает, что вы имеете в виду, и <> больше не нужны.

Более подробная информация:

person manlio    schedule 18.03.2019

... если я хочу использовать класс...

Это распространенный источник путаницы. Шаблон класса — это не класс, а шаблон, из которого генерируются классы. Угловые скобки сообщают компилятору, что вы хотите сгенерировать класс из шаблона класса с заданными аргументами шаблона, без угловых скобок у вас есть шаблон.

template <typename T = int>
struct TemplateClass {...};

template <template class T<typename> >
void f() {
   T<int> t; ...
}
template <typename T>
void g() {
   T t; ...
}

f<TemplateClass>();     // Accepts a template with a single type argument
g<TemplateClass<> >();  // Accepts a type, that can be generated out of the template

Язык не допускает сосуществования шаблона и типа с одним и тем же именем в одном и том же пространстве имен, поэтому ответ заключается в том, что это невозможно. Вы можете создать псевдоним типа, но вам придется дать ему другое имя.

person David Rodríguez - dribeas    schedule 15.04.2013
comment
Дэвид, спасибо за хороший ответ, он хорошо служил в течение последних нескольких лет. Но начиная с С++ 17, я думаю, что ответ @manlio подходит лучше. Поэтому я переключил принятый ответ. - person user1810087; 27.06.2019

Вы можете использовать typedef...

typedef tt<> tt_;

А затем просто используйте tt_.

person ForEveR    schedule 15.04.2013
comment
Хм. что typedef экономит вам один символ для ввода каждый раз, когда вы используете tt<>. Сам typedef, включая пробелы и новую строку в конце, занимает 18 символов. Плюс потеря читабельности, так как понятно, что tt<> относится к шаблону, а tt_ может быть чем-то другим. Вы по-прежнему не можете использовать одно и то же имя для шаблона и его экземпляра по умолчанию. Так оно того стоит? ;) - person Arne Mertz; 15.04.2013
comment
Как насчет typedef detail_::tt<> tt'? - person Ben Hymers; 15.04.2013