Каковы некоторые виды использования 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 102

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.

от предложение вы можете увидеть больше предполагаемого использования.