3

ファンクターをパラメーターとして受け入れ、後で呼び出すことができるテンプレート関数を作成しようとしていました。プログラムは次のとおりです。

#include <iostream>
#include <functional>
using namespace std;

template<typename R, typename... Args>
R call(function<R(Args...)> fun, Args... args)
{
    cout << "call@ " << __LINE__ <<endl;
    return fun(args...);
}

int main()
{
    cout << call(std::plus<int>(),1,2) <<endl;
    return 0;
}

G++ は次のように不満を述べています。

g++ -c -Wall -std=c++0x -I../include a.cpp -o a.o
a.cpp: In function ‘int main()’:
a.cpp:16:38: error: no matching function for call to ‘call(std::plus<int>, int, int)’
a.cpp:16:38: note: candidate is:
a.cpp:7:3: note: template<class R, class ... Args> R call(std::function<_Res(_ArgTypes ...)>, Args ...)
a.cpp:7:3: note:   template argument deduction/substitution failed:
a.cpp:16:38: note:   ‘std::plus<int>’ is not derived from ‘std::function<_Res(_ArgTypes ...)>’
make: *** [a.o] Error 1

と推測std::plus<int>()できると思いますがstd::function<int(int,int)>、そうではありませんでした。それはなぜですか?GCCはgcc version 4.7.2 20120921 (Red Hat 4.7.2-2) (GCC)

4

3 に答える 3

6

std::plus() は std::function と推測できると思います

いいえ。 type のオブジェクトを渡したので、推測できませんでしたstd::plus<int>

あなたの場合、特定の署名で呼び出すことができるさまざまな関数/関数オブジェクトを格納するときに通常使用するため、使用する必要はありません。std::function

callこれにより、 を使用せずに、元の型が推定された関数/関数オブジェクトを関数に直接受け入れることができますstd::function。また、パラメーターを受け入れるときに完全転送を使用std::forwardし、関数/関数オブジェクトに引数として渡すときに使用することもできます。また、関数の戻り値の型を の戻り値の型として使用する必要がありますcall。そのためには、 C++11 の末尾の戻り値の型をdecltype使用します。

#include <iostream>
#include <functional>
using namespace std;

template<typename R, typename... Args>
auto call(R fun, Args&&... args) -> decltype(fun(std::forward<Args>(args)...))
{
    cout << "call@ " << __LINE__ <<endl;
    return fun(std::forward<Args>(args)...);
}

int main()
{
    cout << call(std::plus<int>(),1,2) <<endl;
    return 0;
}

ライブコード


@Jan Hudecがコメントしたように、関数が渡されても、__LINE__へのすべての呼び出しで常に同じ結果になります。call

于 2013-09-04T06:14:22.940 に答える
3

テンプレートの引数を推測できません。

関数のシグネチャを次のように変更することをお勧めします。

template<typename F, typename... Args>
auto call(F fun, Args... args )
    -> decltype( fun(args...) )
于 2013-09-04T06:10:10.607 に答える