почему auto нельзя использовать для перегрузки функций?
Я понимаю, что с помощью templates
является одним из оцененных способов перегрузки, но мне было интересно, почему auto
не может использоваться для вычета типа параметра функции, следовательно, помогая перегрузке функции?
N3690
говорит в 7.6.1.4 / 3, что лямбда-выражение может быть сделано общим с помощью auto, предоставляя этот пример
auto glambda = [](int i, auto a) { return i; };//OK: a generic lambda
(Примечание: это не упоминается в N3485)
1).почему я не могу сделать аналогичную вещь для нормальной функции для е.г
void swap(auto& param1, decltype(param1)& param2)
{
decltype(param1) temp = param1;
param1 = param2;
param2 = temp;
}
это дает ошибки error : parameters declared auto
.
из N3690 7.1.6.4 / 4
тип переменной, объявленной с помощью auto или decltype (auto) выводится из его инициализатор. Это использование разрешено при объявлении переменных в блоке (6.3), в области пространства имен (3.3.6) и в инструкции for-init (6.5.3).[...]
я ошибаюсь, предполагая, что param1
и param2
попадают под область блока и, следовательно, имеют право для автоматического вычета?
2). если бы такая функция была разрешена, каковы были бы подводные камни?
я использую gcc 4.8.1.
спасибо
4 ответов
n3690 7.1.6.4 / 2
7.1.6.4/3Тип заполнителя может отображаться с помощью Декларатора функций в decl-specifier-seq, type-specifier-seq, conversion-function-id или trailing-return-type в любом контексте, где такой Декларатор действителен.
7.1.6.4/4Если авто-спецификатор типа отображается как один из Децл-спецификаторов в Децл-спецификаторе-seq параметра- объявление лямбда-выражения лямбда-универсальный лямбда.
7.1.6.4/5Тип переменной, объявленной с помощью auto или decltype(auto), выводится из ее инициализатора. Это использование-al- lowed при объявлении переменных в блоке (6.3), в области пространства имен (3.3.6) и в инструкции for-init (6.5.3). auto или decltype (auto) должны отображаться как один из описателей decl в описателе decl-seq и decl- спецификатор-seq должен сопровождаться одним или несколькими init-деклараторами, каждый из которых должен иметь непустой первоначальный- Изер.
Разрешается только такое использование. Любое другое использование запрещено (в частности, использование втип заполнителя также может использоваться при объявлении переменной в условии оператора выделения (6.4) или оператор итерации (6.5) в спецификаторе типа-seq в new-type-id или Type-id нового выражения (5.3.4), в объявление для диапазона и при объявлении статического элемента данных с отображаемым инициализатором скобки или равенства внутри спецификации-члена определения класса (9.4.2).
parameter-declaration-clause
).
7.1.6.4/6
Программа, которая использует auto или decltype(авто) в контексте, явно не разрешенном в этом разделе, плохо сформирована.
N3690-это проект комитета для C++14, т. е. для следующего стандарта C++, который еще не выпущен и который может быть еще не реализован в большинстве компиляторов. Поэтому вы должны обратиться к документации вашего компилятора, если реализованы общие лямбды - я думаю, что это не так.
однако с gcc у вас есть хорошие шансы, что функции C++14 будут реализованы до официального выпуска нового стандарта, хотя вам может потребоваться явно включить поддержку C++14 с помощью команды флаг линии. Глядя на документы, это должно быть -std=gnu++1y
по данным этот сайт универсальные лямбды еще не реализованы в GCC.
обновление:
Что касается обычных общих функций, использующих auto
параметры: они не существуют и не придет в следующий раз. Причина в том, что шаблонные функции являются только немного более подробными для ввода и более мощными, так как вы можете ссылаться на типы и напрямую применять метафункции шаблонов к их. В generic lambdas это можно сделать только с помощью decltype(a)
, который немного более утомителен и должен использоваться с осторожностью, потому что он ведет себя немного иначе, чем вывод аргумента шаблона.
Дополнительный бонус с шаблонами по сравнению с auto params-это немного больше typesafety или выразительности:
void func(auto a, auto b); //a and b might be different types
template <class T>
void func(T a, T b); //a and b must be the same type
почему я не могу сделать аналогичную вещь для нормальной функции для e.g
void swap(auto& param1, decltype(param1)& param2)
просто потому, что язык не позволяет это сделать. До auto
был (re)изобретен в C++11, что вы хотите, было достижимо через шаблоны:
template <class T, class U>
void swap(T& param1, U& param2);
C++11 также содержит лямбда-выражения, А C++14, вероятно, представит полиморфные лямбды, которые, в основном, лямбды, чьи operator ()
шаблоны. Например, для полиморфных лямбд рассматривался синтаксис, аналогичный синтаксису шаблонов (пример взят из N3418)
[]<class T>(T* p) { /* ... */ }
в конце предпочтительный синтаксис использовал auto
вместо того, чтобы вводить список параметров шаблона.
это правда, что можно было бы рассмотреть возможность расширения этого синтаксиса terser на шаблоны функций (как предлагает OP), но, насколько я знаю, комитет не рассматривал это возможность. Это может сделать в будущем, но кто-то должен официально предложить это. Это может быть "хорошая функция", но ИМХО это просто синтаксический сахар, который не приносит много языка.
кроме того, я не вижу, как этот синтаксис terser (без списков параметров шаблона) может использоваться для классов шаблонов, и, возможно, расхождение синтаксиса для функций шаблона с синтаксисом классов шаблонов не стоит делать.
уже есть способ написать то, что вы хотели: -
template <class T>
void swap(T& param1, T& param2)
{
T temp = param1;
param1 = param2;
param2 = temp;
}
Итак, зачем создавать новый синтаксис, который не позволяет вам делать то, что вы не могли сделать раньше. Предлагаемое изменение в lambdas-разрешить общие lambdas, которые вы не могли сделать раньше, и я думаю, что любой синтаксис, использующий синтаксис шаблона, был бы уродливым здесь.