Тип возврата С++ lambda

Я пишу функцию шаблона, которая принимает объект функции (теперь, лямбда) в качестве параметра, с типом данных лямбда в качестве параметра шаблона и возвращает тот же самый тип, который возвращается лямбда. Вот так:

template<typename tfunctor,="" typename="" treturn="">
TReturn MyFunc(TFunctor &Func, TReturn) //The second arg is just to keep the template spec happy
{
 return Func();
}
</typename>

И код потребления будет выглядеть следующим образом:

int n = MyFunc([](){return 17;}, int());

Мне не нравится уродливый способ указания типа данных возврата. Есть ли встроенный typedef в генерируемый компилятором лямбда-класс, который даст мне его возвращаемый тип? Так что MyFunc может так или иначе выглядеть:

template<typename tfunctor="">
TFunctor::return_type MyFunc(TFunctor &Func)
{ //...
</typename>

Я хочу, чтобы он возвращал тот же тип, что и лямбда, без явного указания этого типа.

EDIT: на данный момент все лямбды, с которыми я связан, являются бесспорными. Захват переменной также делает трюк.

1 ответ

Так как тип возврата может зависеть от аргументов, заданных функтору, вам нужно указать их где-нибудь, чтобы запросить возвращаемый тип. Поэтому, говоря об общих функторах (не ограничивая их (неэквивалентными) лямбдами), невозможно определить тип возврата, если не знает типы аргументов.

С++ 11 имеет ключевое слово decltype, которое может использоваться в сочетании с типом возвращаемого возврата, чтобы указать тип возврата вашей функции, называя выражение, которое может зависеть от аргументов функции (здесь это зависит на чем Func):

template<typename tfunctor="">
auto MyFunc(TFunctor &Func) -> decltype(Func(/* some arguments */))
{ ... }
</typename>

Итак, если вы хотите назвать его, например, без аргумента (я предполагаю это, глядя на ваш пример лямбда), просто напишите:

template<typename tfunctor="">
auto MyFunc(TFunctor &Func) -> decltype(Func())
{ 
 return Func();
}
</typename>

В С++ 14 вы даже можете полностью опустить возвращаемый тип и просто написать

template<typename tfunctor="">
auto MyFunc(TFunctor &Func)
{ 
 return Func();
}
</typename>

Обратите внимание, что даже в С++ 03 вам не нужно предоставлять другой аргумент функции; достаточно другого аргумента шаблона:

template<typename treturn,="" typename="" tfunctor="">
TReturn MyFunc(TFunctor &Func)
{
 return Func();
}
int n = MyFunc<int>(someFunctorReturningAnInt);
</int></typename>

licensed under cc by-sa 3.0 with attribution.