Просвещение Использование С++ 11 decltype

Я только что видел этот действительно приятный разговор Rock Hard: С++ Evolution Борис Джабес. В разделе разговора о программировании на высшем заказе он говорит, что следующее является примером функции, более общей по отношению к ее возвращаемому типу, и приводит к меньшему числу перегрузок функций шаблона

template <typename Func>
auto deduce(const Func & f) -> decltype(f())
{..}

Это может быть реализовано с использованием простого синтаксиса шаблона следующим образом

template <typename Func>
Func deduce(const Func & f)
{..}

поэтому я думаю, что выбранный пример действительно не показывает уникальную мощность decltype. Может ли кто-нибудь привести пример такого более просветительного использования decltype?

Ответ 1

Ваши подозрения неверны.

void f() { }

Теперь deduce(&f) имеет тип void, но с вашим переписанием он имеет тип void(*)(). В любом случае, везде, где вы хотите получить тип выражения или декларации, вы используете decltype (обратите внимание на тонкую разницу между этими двумя. decltype(x) не обязательно совпадает с decltype((x))).

Например, вероятно, что ваша реализация стандартной библиотеки где-то содержит строки типа

using size_t = decltype(sizeof(0));
using ptrdiff_t = decltype((int*)0 - (int*)0);
using nullptr_t = decltype(nullptr);

Поиск правильного типа возврата add является сложной проблемой на протяжении всего С++. Теперь это простое упражнение.

template<typename A, typename B> 
auto add(A const& a, B const& b) -> decltype(a + b) { return a + b; }

Мало известно, что вы можете использовать decltype до :: и в псевдо-деструкторе name

// has no effect
(0).~decltype(0)();

// it and ite will be iterators into an initializer list 
auto x = { 1, 2, 3 };
decltype(x)::iterator it = x.begin(), ite = x.end();

Ответ 2

std::for_each(c.begin(), c.end(), [](decltype (c.front()) val){val*=2;});

Автообновление параметра value_type контейнера c не может быть выполнено без decltype.

Ответ 3

Одно место, в котором я его использую, - это то, где мне нужно создать переменную, которая должна иметь тот же тип другой переменной. но я не уверен, что в будущем тип останется таким же или нет.

void foo(int a)//maybe in future type of a changed
{
    decltype(a) b;
    //do something with b
}