2

Я использую 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 

Любая идея, почему и как Исправить это?

+0

думать о функции-члене класса С, принимая аргументы типа А и В, как же, как и свободная функция принимает 3 аргумента, один из типа С, другой тип A и другое типа B. Ключевое слово «this» означает указатель на этот скрытый объект типа C. – brunocodutra

ответ

4

Синтаксис указателей на элементы по-прежнему применяется. Вы должны написать:

typedef int (S::*func)(int a, int b); 
    template<func F> int do_it(int a, int b) { 
     return (this->*F)(a, b); 
    } 

Использование указателя для элемента всегда требуется связать объект с ней - вот, это имеет смысл, вы могли бы назвать указатель на this.

+0

Это делает трюк! Thanx! – cxxl

1

Похоже, вам просто нужно вызвать указатель на функцию члена на объекте:

template<func F> int do_it(int a, int b) { 
     return (this->*F)(a, b); 
} 

Указатели на член всегда должны называться на объекте, в отличии от функций бесплатно и статического члена, поэтому вам нужен вышеупомянутый синтаксис.

2

Указатели функций-функций должны быть вызваны на объект; В отличие от обычного вызова функции-члена, this должен быть указан в явном виде:

(this->*F)(a,b); 

Хотя, если функция не требует доступа this, возможно, он должен быть статическим (или не являющегося членом), указанный нормальный указатель функции.

1

Вы должны предоставить объект при вызове указатель на meber функцию:

(this->*F)(a, b); 
0

один пункт дальше: написать свой «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); 

Если вы намерены использовать его внутри своего класса с членом функцию, просто привяжите его к этому. Использование подталкивание :: привязок,

int foo(int a, int b) { 
     return do_it(boost::bind(&S::add,this,_1,_2),a,b) ; 
Смежные вопросы