Перегруженная функция класса C ++ (с аргументом std :: function) не видна - PullRequest
0 голосов
/ 27 сентября 2018

Позвольте мне проиллюстрировать мой вопрос следующим примером.Предположим, у нас есть базовый класс, который определяет метод Exec , который принимает один аргумент любого типа (шаблона).Метод Exec вызывает затем метод Вызов , который был перегружен для получения в качестве аргумента объекта std :: function с другими параметрами.

Теперь предположим, что у нас есть производнаякласс, который наследуется после Base и перегружает Exec , поэтому он принимает в качестве аргумента еще один объект std :: function (с другим набором аргументов).

Что-то вроде:

struct Base
{
  template<typename Func>
  static void Exec( Func func )
  {
    Call( func );
  }

  static void Call( std::function<void(void)> func )
  {
    func();
  }

  /*other definitions of Call for other std::functions*/
};

struct Derived : public Base
{
  using Base::Exec;

  static void Exec( std::function<void(int)> func )
  {
    func( 10 );
  }
};

Теперь предположим, что мы хотим вызвать:

Derived::Exec( []( int i ){std::cout << i << std::endl;} );

Это даст следующую ошибку компиляции (я пробовал с g ++ 4.8.5 и 8.1.1):

error: no matching function for call to 'Base::Call(main(int, char**)::<lambda(int)>&)'

Мой вопрос: почему компилятор не видит определения Exec в классе Derived (void Derived::Exec( std::function<void(int)> func ))?Я ожидаю, что при разрешении перегрузки будет выбран Derived::Exec, так как он наиболее подходит для данного аргумента:

 []( int i ){std::cout << i << std::endl;}

Чего мне не хватает?

Ответы [ 2 ]

0 голосов
/ 27 сентября 2018

Лямбда []( int i ){std::cout << i << std::endl;} конвертируется в std::function<void(int)>, а не в std::function<void(void)>.

Даже когда функция шаблона в Base выбирается из-за идеального соответствия, внутри нее вы передаете func в Base::Call, которые принимают что-то конвертируемое в std::function<void(void)>, а лямбда - нет.Derived::Call никогда не выбирается из-за статической отправки, вот причина ошибки.

0 голосов
/ 27 сентября 2018

Лямбда-выражения производят замыкания , которые имеют анонимные и уникальные типы.Эти типы совершенно не связаны с std::function.

Ваш template лучше подходит, так как он может определить точный тип замыкания .Для вызова перегрузки не template потребуется создать экземпляр std::function из замыкания (не точное совпадение).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...