Обнаружение типов параметров из общей лямбды — ошибка компиляции с GCC

Я написал некоторый код, который извлекает типы неавтоматических параметров при задании универсальной лямбда-функции. Как вы можете видеть из приведенного ниже кода, идея состоит в том, чтобы вызвать функцию 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);
}

5

Решение

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

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 а не совсем свежая дженерик-лямбда?

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]