Я использую Visual C ++ 2012. Я хочу параметризовать функцию шаблона с указателем на другую функцию. Все это прекрасно работает вне класса:
int add(int a, int b) {
return a + b;
}
typedef int (*func)(int a, int b);
template<func F> int do_it(int a, int b) {
return F(a, b);
}
int foo(int a, int b) {
return do_it<add>(a, b);
}
Visual C ++ 2012 прекрасно компилирует и оптимизирует это.
Теперь я помещаю его в класс и настраиваю для указателя на член:
struct S {
int add(int a, int b) {
return a + b;
}
typedef int (S::*func)(int a, int b);
template<func F> int do_it(int a, int b) {
return F(a, b); // <-- here be error!
}
int foo(int a, int b) {
return do_it<&S::add>(a, b);
}
};
S s;
int bar(int a, int b) {
return s.foo(a, b);
}
Но это дает мне ошибку компилятора:
Microsoft (R) C/C++ Optimizing Compiler Version 17.00.51106.1 for x86
Copyright (C) Microsoft Corporation. All rights reserved.
x2.cpp
x2.cpp(7) : error C2064: term does not evaluate to a function taking 2 arguments
x2.cpp(10) : see reference to function template instantiation 'int S::do_it<int S::add(int,int)>(int,int)' being compiled
Есть идеи почему и как это исправить?
Синтаксис для указателей на члены все еще применяется. Вы должны написать:
typedef int (S::*func)(int a, int b);
template<func F> int do_it(int a, int b) {
return (this->*F)(a, b);
}
Использование указателя на член всегда требует привязки объекта к нему — здесь имеет смысл вызвать указатель на this
,
Указатели на функции-члены должны вызываться для объекта; в отличие от обычного вызова функции-члена, this
должен быть указан явно:
(this->*F)(a,b);
Хотя, если функция не нуждается в доступе this
возможно, он должен быть статическим (или не являющимся членом), указанным обычным указателем на функцию.
Похоже, вам просто нужно вызвать указатель на функцию-член объекта:
template<func F> int do_it(int a, int b) {
return (this->*F)(a, b);
}
Указатели на члены всегда должны вызываться на объекте, в отличие от свободных и статических функций-членов, поэтому вам необходим вышеуказанный синтаксис.
Вы должны предоставить объект при вызове функции указателя на meber:
(this->*F)(a, b);
Еще один момент: напишите ваш «do_it» в более общем виде
template<class F> int do_it(F f, int a, int b) {
return f(a, b); }
Теперь вы можете передать ему любую функцию из двух целых чисел:
int mul(int a, int b) { return a*b ; }
S s;
s.do_it(mul,2,3);
Когда вы намереваетесь использовать его внутри своего класса с функцией-членом, просто свяжите это с этим. Используя boost :: bind,
int foo(int a, int b) {
return do_it( boost::bind(&S::add,this,_1,_2),a,b) ;