Каковы некоторые виды использования decltype (auto)?
В c++14 the фразеологизм.
как правило, его использование разрешить auto
объявления для использования decltype
правила по данному выражению.
Поиск примеров "хорошего" использования идиомы я могу думать только о таких вещах, как следующее (by Скотт Мейерс), а именно для функция возвращает тип вычитания:
template<typename ContainerType, typename IndexType> // C++14
decltype(auto) grab(ContainerType&& container, IndexType&& index)
{
authenticateUser();
return std::forward<ContainerType>(container)[std::forward<IndexType>(index)];
}
есть ли другие примеры, когда эта новая функция языка полезно?
2 ответа:
возврат типа переадресации в общий код
для неродового кода, как и в первом примере, который вы дали, вы можете вручную выбрать, чтобы получить ссылку в качестве типа возврата:
auto const& Example(int const& i) { return i; }
а в общий код вы хотите быть в состоянии отлично вперед тип возврата не зная, имеете ли вы дело с ссылкой или значением.
decltype(auto)
дает вам эту возможность:template<class Fun, class... Args> decltype(auto) Example(Fun fun, Args&&... args) { return fun(std::forward<Args>(args)...); }
задержка вычета типа возврата в рекурсивные шаблоны
на это Q & A несколько дней назад при создании экземпляра шаблона возникла бесконечная рекурсия, когда возвращаемый тип шаблона был указан как
decltype(iter(Int<i-1>{}))
вместоdecltype(auto)
.template<int i> struct Int {}; constexpr auto iter(Int<0>) -> Int<0>; template<int i> constexpr auto iter(Int<i>) -> decltype(auto) { return iter(Int<i-1>{}); } int main() { decltype(iter(Int<10>{})) a; }
decltype(auto)
здесь задержите вычет типа возврата после того, как пыль осела инстанцирования шаблона.другие виды использования
вы также можете использовать
decltype(auto)
в других контексты, например проект стандарта N3936 также указано7.1.6.4 автоматический спецификатор [dcl.спекуляция.авто]
1 The
auto
иdecltype(auto)
спецификаторы типа обозначают заполнитель тип, который будет заменен позже, либо путем вычитания из инициализатор или по явной спецификации с типом трейлинг-возврата. Элементauto
спецификатор типа также используется для обозначения того, что лямбда является универсальный лямбда.2 тип заполнителя могут появиться С помощью Декларатора функций в Децл-спецификатор-seq, тип-спецификатор-seq, преобразования-функции-идентификатор, или трейлинг-возвращение-тип, в любом контексте, где такой Декларатор действителен. Если функция Декларатор включает в себя тип конечного возврата (8.3.5), который определяет объявленный тип возврата функции. Если объявленный тип возврата функции содержит тип заполнителя, тип возврата функции является вывести из операторов return в теле функции, если таковые имеются.
проект также содержит этот пример инициализации переменной:
int i; int&& f(); auto x3a = i; // decltype(x3a) is int decltype(auto) x3d = i; // decltype(x3d) is int auto x4a = (i); // decltype(x4a) is int decltype(auto) x4d = (i); // decltype(x4d) is int& auto x5a = f(); // decltype(x5a) is int decltype(auto) x5d = f(); // decltype(x5d) is int&& auto x6a = { 1, 2 }; // decltype(x6a) is std::initializer_list<int> decltype(auto) x6d = { 1, 2 }; // error, { 1, 2 } is not an expression auto *x7a = &i; // decltype(x7a) is int* decltype(auto)*x7d = &i; // error, declared type is not plain decltype(auto)
цитируя материал из здесь:
decltype(auto)
в первую очередь полезна для вывод возвращаемого типа функций пересылки и подобных оболочек, где вы хотите, чтобы тип точно "отслеживал" какое-то выражение, которое вы вызываете.например, учитывая следующие функции:
string lookup1(); string& lookup2();
- в C++11 мы могли бы написать следующие функции-оболочки которые не забывают сохранить ссылочность возвращаемого типа:
string look_up_a_string_1() { return lookup1(); } string& look_up_a_string_2() { return lookup2(); }
- в C++14, мы можем автоматизировать, что:
decltype(auto) look_up_a_string_1() { return lookup1(); } decltype(auto) look_up_a_string_2() { return lookup2(); }
- ,
decltype(auto)
не предназначено быть широко используемой характеристикой за этим.в частности, хотя он может быть использован для объявлять локальные переменные, делая это, вероятно, просто антипаттерн, так как местный ссылочность переменной не должна зависеть от выражения инициализации.
кроме того, он чувствителен к тому, как вы пишете оператор return.
например, две функции имеют разные типы возвращаемых значений:
decltype(auto) look_up_a_string_1() { auto str = lookup1(); return str; } decltype(auto) look_up_a_string_2() { auto str = lookup2(); return(str); }
- первый возвращает
string
, второй возвращаетstring&
, который является ссылкой на локальную переменнуюstr
.от предложение вы можете увидеть больше предполагаемого использования.