Когда можно опускать пустые угловые скобки?

В этом вопросе можно использовать std::less с пустыми скобками std::less<>, но нельзя без них std::less. В то время как этот код принимает оба варианта:

std::sort(v.begin(), v.end(), std::less()); 

std::sort(v.begin(), v.end(), std::less<>()); 

Почему так? Когда можно опустить <>, а когда нельзя?


Ответы (1 шт):

Автор решения: HolyBlackCat

std::less - шаблон класса. Возможность не писать после него шаблонные аргументы называется CTAD (class template argument deduction - вывод аргументов для шаблонов классов).

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

Ищем "class template argument deduction" в предметном указателе стандарта, находим:

[dcl.type.class.deduct]/1

If a placeholder for a deduced class type appears as a decl-specifier in the decl-specifier-seq of an initializing declaration ([dcl.init]) of a variable, the declared type of the variable shall be cv T, where T is the placeholder.

Т. е. первый случай - это разрешено в "инициализирующих объявлениях" переменных, если в типе кроме имени класса нет ничего кроме const и volatile (никаких *, [], и т. п.).

Что еще за "инициализирующее объявление"? [dcl.init.general]/21 объясняет, что это то же самое, что определение переменной, за исключением вот этой ситуации:

struct A {static const int x = 1;};
const int A::x;

В которой инициализирующее объявление - первое (потому что там инициализатор), а определение - второе.

Но это не единственный случай, где это разрешено. Читаем дальше:

[dcl.type.class.deduct]/2

A placeholder for a deduced class type can also be used in the type-specifier-seq in the new-type-id or type-id of a new-expression ([expr.new]), as the simple-type-specifier in an explicit type conversion (functional notation), or as the type-specifier in the parameter-declaration of a template-parameter ([temp.param]). A placeholder for a deduced class type shall not appear in any other context.

Т. е. еще это разрешено в:

→ Ссылка