2016-06-22 7 views
5

Я написал код, который извлекает типы неавтоматических параметров при предоставлении общей лямбда-функции. Как вы можете видеть в приведенном ниже коде, идея состоит в вызове функции connect с общей лямбдой и предоставлении аргументов для автоматических параметров (которые всегда будут в начале в моем случае использования). Поэтому в приведенном ниже коде моя цель состояла в том, чтобы обнаружить, что второй параметр имеет тип float.Обнаружение типов параметров из общей ошибки лямбда-компиляции с помощью GCC

Код работает нормально с clang 3.8, но он не компилируется с gcc 6.1.1, поэтому мне было интересно, было ли это ошибкой в ​​gcc или это просто недопустимый код C++? Могу ли я предположить, что общая лямбда реализована с помощью функции templated 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); 
} 

Ошибка, НКУ дает это:

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); 
} 

ответ

1

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

int main() { 
    using function = void (*)(int, float); 
    function a = [](auto, float){}; 
} 

Престола lambda from cppreference:


Для новейшей версии вашего вопроса, что реализация удовлетворяет оба Составители:

template <typename Func, typename... ProvidedArgs> 
void connect(Func func, ProvidedArgs... providedArgs) 
{ 
    auto mf = &Func::template operator()<ProvidedArgs...>; 
    findArgTypes(mf, func, providedArgs...); 
} 

Я думаю, что это ошибка компилятора GCC, что НКУ потребности в этом auto локальных переменную для правильной работы ...

Кстати, один вопрос - одна ошибка в clang, одна в gcc - я действительно советую вам найти более простой способ достичь ваших целей - может быть, стоит просто использовать std::function вместо совершенно новой родовой лямбда?

+0

Этот код, похоже, компилируется с gcc, но не с clang. Но изменение моего кода для принятия 'void (*) (AllArgs ...)' как первого параметра findArgTypes по-прежнему дает ту же ошибку с gcc (и больше не работает с clang). Захват локальной переменной также, похоже, не имеет значения. – texus

+0

Вам нужны две перегруженные функции - одна для бесплатных функций, одна для функций объекта - или просто немного измените ваш дизайн ... – PiotrNycz

+0

clang может быть неправильным - см. Пример со связанной страницы: 'int & (* fpi) (int *) = [] (авто * a) -> auto & {return * a; }; // ok' – PiotrNycz

 Смежные вопросы

  • Нет связанных вопросов^_^