G ++, кажется, принимает любую комбинацию auto
а также decltype(auto)
в качестве начального и конечного типов возврата:
int a;
auto f() { return (a); } // int
auto g() -> auto { return (a); } // int
auto h() -> decltype(auto) { return (a); } // int&
decltype(auto) i() { return (a); } // int&
decltype(auto) j() -> auto { return (a); } // int
decltype(auto) k() -> decltype(auto) { return (a); } // int&
Тем не менее, лязг отвергает j
а также k
говоря: ошибка: функция с конечным типом возврата должна указывать тип возврата «auto», а не «decltype (auto)» (демонстрация).
Какой компилятор правильный? Какое правило (auto
или же decltype(auto)
) следует использовать в каждом конкретном случае? И имеет ли смысл использовать тип заполнителя в задний обратный тип?
auto
требуется при введении задний обратный тип.
§8.3.5 [dcl.fct] / 2
В декларации
T D
гдеD
имеет форму
D1 (
parameter-declaration-clause
)cv-qualifier-seq
выбирать
ref-qualifier
выбиратьexception-specification
выбиратьattribute-specifier-seq
выбиратьtrailing-return-type
и тип содержимого описатель-идентификатор в декларации
T D1
является «производнымописатель-типа списокT
»,
T
должен быть единственным Тип Спецификатор авто. […]
Смотрите также Основной выпуск 1852 для очевидного противоречия с [dcl.spec.auto] / 1.
Изменить после @Xeo конструктивные комментарии:
Похоже, что эта проблема обусловлена противоречием между двумя местами проекта стандарта.
Согласно проекту стандарта § 7.1.6.4 авто спецификатор [dcl.spec.auto]:
1
auto
а такжеdecltype(auto)
спецификаторы типа обозначают тип заполнителя это будет заменено позже, либо вычетом из инициализатора, либо явной спецификацией с типом конечного возврата. Авто-тип-спецификатор
также используется, чтобы показать, что лямбда — это общая лямбда.
2
Тип заполнителя может появиться с помощью объявления функции в decl-specier-seq, type-specier-seq,
ID-функции преобразования или задний обратный тип, в любом контексте, где такой декларатор действителен. Если функция
Объявление содержит конечный тип возврата (8.3.5), который определяет объявленный тип возврата функции.
Если объявленный тип возврата функции содержит тип заполнителя, тип возврата функции
выводится из операторов возврата в теле функции, если таковые имеются.
Единственная интерпретация вышеизложенного предполагает, что в Clang есть ошибка.
Тем не менее, как основной вопрос 1852 Указанное выше противоречит § 8.3.5 / 2 Функции [dcl.fct] и должен быть изменен. Статус вопроса готов, что говорит о том, что изменения были приняты.
Также, у GCC есть ошибка, о которой нужно сообщить.