Я написал некоторый код, который извлекает типы неавтоматических параметров при задании универсальной лямбда-функции. Как вы можете видеть из приведенного ниже кода, идея состоит в том, чтобы вызвать функцию connect с общей лямбдой и предоставить аргументы для автоматических параметров (которые всегда будут впереди в моем случае использования). Поэтому в приведенном ниже коде моей целью было обнаружить, что второй параметр имеет тип float.
Код отлично работает с clang 3.8, но не компилируется с gcc 6.1.1, поэтому мне было интересно, была ли это ошибка в gcc или это просто недопустимый код c ++? Могу ли я предположить, что универсальная лямбда реализована с помощью шаблонной функции operator () или это зависит от компилятора?
template <typename Functor, typename... AllArgs, typename... ProvidedArgs>
void findArgTypes(void(Functor::*)(AllArgs...) const, Functor, ProvidedArgs...)
{
// AllArgs == int, float
// ProvidedArgs == int
}
template <typename Func, typename... ProvidedArgs>
void connect(Func func, ProvidedArgs... providedArgs)
{
findArgTypes(&Func::template operator()<ProvidedArgs...>, func, providedArgs...);
}
int main()
{
int tmp = 0;
connect([&](auto, float){ ++tmp; }, 0);
}
Ошибка, которую дает gcc, такова:
main.cpp: In instantiation of ‘void connect(Func, ProvidedArgs ...) [with Func = main()::<lambda(auto:1, float)>; ProvidedArgs = {int}]’:
main.cpp:16:33: required from here
main.cpp:11:17: error: no matches converting function ‘operator()’ to type ‘void (struct main()::<lambda(auto:1, float)>::*)() const’
findArgTypes(&Func::template operator()<ProvidedArgs...>, func, providedArgs...);
~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
main.cpp:16:27: note: candidate is: template<class auto:1> main()::<lambda(auto:1, float)>
connect([](auto, float){}, 0);
^
Удаление const
в findArgTypes дает тот же результат.
Использование следующего кода работает с обоими компиляторами:
struct Foo
{
template <typename T>
void operator()(T, float) const {}
};
int main()
{
Foo f;
connect(f, 0);
}
У вас ошибка, потому что вы ожидаете функтор (объект), но лямбда с пустым захватом может быть преобразована в свободную функцию:
int main() {
using function = void (*)(int, float);
function a = [](auto, float){};
}
Увидеть лямбда от cppreference:
Для новейший Версия вашего вопроса о том, что реализация удовлетворяет обоим компиляторам:
template <typename Func, typename... ProvidedArgs>
void connect(Func func, ProvidedArgs... providedArgs)
{
auto mf = &Func::template operator()<ProvidedArgs...>;
findArgTypes(mf, func, providedArgs...);
}
Я думаю, что это ошибка компилятора gcc, что gcc нуждается в этом auto
локальная переменная для правильной работы …
Кстати, один вопрос — одна ошибка в clang, одна в gcc — я действительно советую вам найти более простой способ достижения ваших целей — возможно, стоит подумать о том, чтобы просто использовать std::function
а не совсем свежая дженерик-лямбда?
Других решений пока нет …