5

c++ でルーチンを実装する 3 つの方法を検討してください: ファンクター、メンバー関数、および非メンバー関数を使用します。例えば、

#include <iostream>
#include <string>

using std::cout;
using std::endl;
using std::string;

class FOO
{
public:
  void operator() (string word)         // first: functor
  {
    cout << word << endl;
  }

  void m_function(string word)          // second: member-function
  {
    cout << word << endl;
  }
} FUNCTOR;


void function(string word)              // third: non-member function
{
  cout << word << endl;
}

上記の 3 つの関数を呼び出すテンプレート関数を考えてみましょう。

template<class T>
void eval(T fun)
{
  fun("Using an external function");
}

FOO::m_functionevalを介して呼び出す適切な方法は何ですか? 私は試した:

FUNCTOR("Normal call");               // OK: call to ‘void FOO::operator()(string)‘
eval(FUNCTOR);                        // OK: instantiation of ‘void eval(T) [with T = FOO]’

function("Normal call");              // OK: call to ‘void function(string)’
eval(function);                       // OK: instantiation of ‘void eval(T) [with T = void (*)(string)]’

FUNCTOR.m_function("Normal call");    // OK: call to member-function ‘FOO::m_function(string)’
eval(FUNCTOR.m_function);             // ERROR: cannot convert ‘FOO::m_function’ from type
                                      //        ‘void (FOO::)(std::string) {aka void (FOO::)(string)}’
                                      //        to type ‘void (FOO::*)(std::basic_string<char>)’
                                      // In instantiation of ‘void eval(T) [with T = void (FOO::*)(string)]’:
                                      // ERROR: must use ‘.*’ or ‘->*’ to call pointer-to-member function in ‘fun (...)’, e.g. ‘(... ->* fun) (...)’
4

2 に答える 2

9

メンバー関数へのポインターと関数へのポインターは、2 つの異なる獣です。前者は、暗黙的な最初の引数、thisポインター、つまり、メンバー関数が呼び出されるインスタンスへのポインターを取ります。

通常、メンバー関数を呼び出し可能なオブジェクトとして渡すことができるようにするために、bindそれが呼び出されるインスタンスをplaceholders指定し、後で呼び出し可能なオブジェクトに渡される引数を示すために使用します。あなたの場合

eval(std::bind(&FOO::m_function, &FUNCTOR, std::placeholders::_1));

上記の最初の引数bindは、呼び出したいメンバー関数へのポインターであり、2 番目の引数は、呼び出しFOOたいインスタンスへのポインターですm_functionbind最後の 1 つは、によって作成された callable に渡される最初の引数が、メンバー関数を呼び出すときに使用する必要があることを示すプレースホルダーです。

これを行う別の方法は、 (または) 引数evalを取り、メンバー関数を呼び出すラムダ式を に渡すことです。char const *std::string const&

eval([](char const *c) { FUNCTOR.m_function(c); });

ライブデモ

于 2015-06-03T01:36:47.343 に答える
2

内部evalでは、オブジェクトがないため、メンバー関数を呼び出すことはできません。

あなたはこれに行くかもしれません:

template<class T, class U>
void eval(T&& object, U fun)
{
    (object.*fun)("Using an external function");
}

その後

eval(FUNCTOR, &FOO::m_function);
于 2015-06-03T01:35:40.103 に答える