С++ - <неразрешенный перегруженный тип функции>

В моем классе под названием Mat, я хочу иметь функцию, которая принимает другую функцию в качестве параметра. Прямо сейчас у меня есть 4 функции ниже, но я получаю сообщение об ошибке при вызове print(). Вторая строка дает мне ошибку, но я не понимаю, почему, поскольку первый работает. Единственное отличие заключается в том, что функция f не является членом класса Mat, но f2 is. Ошибка: error: no matching function for call to Mat::test( < unresolved overloaded function type>, int)'

template <typename F>
int Mat::test(F f, int v){
    return f(v);
}

int Mat::f2(int x){
    return x*x;
}

int f(int x){
    return x*x;
}

void Mat::print(){
    printf("%d\n",test(f ,5));    // works
    printf("%d\n",test(f2 ,5));    // does not work
}

Почему это происходит?

Ответы

Ответ 1

Тип pointer-to-member-function отличается от pointer-to-function.

Тип функции различен в зависимости от того, является ли она обычной функцией или нестатической функцией-членом для некоторого класса:

int f(int x);
the type is "int (*)(int)" // since it is an ordinary function

И

int Mat::f2(int x);
the type is "int (Mat::*)(int)" // since it is a non-static member function of class Mat

Примечание: если это статическая функция-член класса Fred, то ее тип такой же, как если бы это была обычная функция: "int (*)(char,float)"

В С++ функции-члены имеют неявный параметр, который указывает на объект (этот указатель внутри функции-члена). Нормальный C функции могут рассматриваться как имеющие другое соглашение о созыве от функций-членов, , поэтому типы их указателей (указатель-член-функция против указателя на функцию) различны и несовместимый. С++ вводит новый тип указателя, , называемый указатель-к-члену, который может быть вызван только путем предоставления объекта.

ПРИМЕЧАНИЕ. Не пытайтесь "отличить" функцию "указатель-член" в указатель на функцию; результат undefined и, вероятно, катастрофический. Например, функция-указатель-член не требуется содержать машинный адрес соответствующей функции. Как было сказано в последнем Например, если у вас есть указатель на регулярную функцию C, используйте либо функция верхнего уровня (нечлена) или статическая (класс) функция-член.

Подробнее об этом здесь и здесь.

Ответ 2

Проблема здесь в том, что f2 является методом на Mat, а f является просто свободной функцией. Вы не можете вызвать f2 самостоятельно, для его вызова ему нужен экземпляр Mat. Самый простой способ это:

printf("%d\n", test([=](int v){return this->f2(v);}, 5));

В = будет записано this, что вам нужно вызвать f2.