私はこのような方法を持っています
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, T (f)(T,U))
{
map<T,U> new;
for(auto it = old.begin(); it != old.end(); ++it)
{
new[it->first] = f(it->first,it->second);
}
return new;
}
そして、あなたはこのようにそれを呼ぶだろうという考えです
BOOST_AUTO_TEST_CASE(MapMapValues_basic)
{
map<int,int> test;
test[1] = 1;
map<int,int> transformedMap = VlcFunctional::mapMapValues(test,
[&](int key, int value) -> int
{
return key + 1;
}
);
}
ただし、エラーが発生します:関数テンプレート「VlcFunctional :: mapMapValues」のインスタンスが引数リストに一致しません。引数のタイプは次のとおりです:(std :: map、std :: allocator >>、__lambda1)
私が間違っていることは何か考えていますか? Visual Studio 2008およびIntel C++コンパイラー11.1
関数はラムダではなく関数ポインターを期待しています。
C++では、一般に3つのタイプの「呼び出し可能オブジェクト」があります。
これらすべてを関数インターフェイスで使用できるようにする場合は、std::function
を使用できます。
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T, U)> f)
{
...
}
これにより、上記の3種類の呼び出し可能なオブジェクトのいずれかを使用して関数を呼び出すことができます。ただし、この利便性の代償として、関数の呼び出しに伴うオーバーヘッドがわずかに発生します(通常は、ヌルポインターのチェック、その後の関数ポインターによる呼び出し)。これは、関数がほぼ確実にインライン化されないことを意味します(多分高度な [〜#〜] wpo [〜#〜])を除く / [〜#〜] lto [〜#〜] )。
あるいは、2番目のパラメーターに任意の型を使用するために、追加のテンプレートパラメーターを追加することもできます。これはより効率的になりますが、使用する関数の型安全性が失われ、コードの肥大化につながる可能性があります。
template<typename T, typename U, typename F>
map<T,U> mapMapValues(map<T,U> old, F f)
パラメーターの型宣言T (f)(T,U)
は、型が 'T
とU
を取り、T
を返す' free functionです。ラムダ、関数オブジェクト、またはそのシグネチャを持つ実際の関数以外のものを渡すことはできません。
これを解決するには、次のようにパラメータのタイプをstd::function<T(T,U)>
に変更します。
template<typename T, typename U>
map<T,U> mapMapValues(map<T,U> old, std::function<T(T,U)>)
{
}
または、次のように、関数の型をテンプレート引数として宣言することもできます。
template<typename T, typename U, typename Fn>
map<T,U> mapMapValues(map<T,U> old, Fn fn)
{
fn(...);
}
この簡単だが自明の例を提供したいと思います。 「呼び出し可能なもの」(関数、関数オブジェクト、ラムダ)を関数またはオブジェクトに渡す方法を示します。
// g++ -std=c++11 thisFile.cpp
#include <iostream>
#include <thread>
using namespace std;
// -----------------------------------------------------------------
class Box {
public:
function<void(string)> theFunction;
bool funValid;
Box () : funValid (false) { }
void setFun (function<void(string)> f) {
theFunction = f;
funValid = true;
}
void callIt () {
if ( ! funValid ) return;
theFunction (" hello from Box ");
}
}; // class
// -----------------------------------------------------------------
class FunClass {
public:
string msg;
FunClass (string m) : msg (m) { }
void operator() (string s) {
cout << msg << s << endl;
}
};
// -----------------------------------------------------------------
void f (string s) {
cout << s << endl;
} // ()
// -----------------------------------------------------------------
void call_it ( void (*pf) (string) ) {
pf( "call_it: hello");
} // ()
// -----------------------------------------------------------------
void call_it1 ( function<void(string)> pf ) {
pf( "call_it1: hello");
} // ()
// -----------------------------------------------------------------
int main() {
int a = 1234;
FunClass fc ( " christmas ");
f("hello");
call_it ( f );
call_it1 ( f );
// conversion ERROR: call_it ( [&] (string s) -> void { cout << s << a << endl; } );
call_it1 ( [&] (string s) -> void { cout << s << a << endl; } );
Box ca;
ca.callIt ();
ca.setFun (f);
ca.callIt ();
ca.setFun ( [&] (string s) -> void { cout << s << a << endl; } );
ca.callIt ();
ca.setFun (fc);
ca.callIt ();
} // ()
これは、関数をパラメーターとして渡す方法の例です。
class YourClass
{
void YourClass::callback(void(*fptr)(int p1, int p2))
{
if(fptr != NULL)
fptr(p1, p2);
}
};
void dummyfunction(int p1, int p2)
{
cout << "inside dummyfunction " << endl;
}
YourClass yc;
// using a dummyfunction as callback
yc.callback(&dummyfunction);
// using a lambda as callback
yc.callback( [&](int p1, int p2) { cout << "inside lambda callback function" << endl; } );
// using a static member function
yc.callback( &aClass::memberfunction );