C++ 模板类错误:函数返回函数

Jav*_*imi 5 c++ templates std-function

我想制作一个简单的记录器,它自动运行函数并返回其值。
该类定义为:

template <typename R, typename... Args>
class Logger3
{

    Logger3(function<R(Args...)> func,
            const string& name):
        func{func},
        name{name}
    {}
    R operator() (Args ...args)
    {
        cout << "Entering " << name << endl;
        R result = func(args...);
        cout << "Exiting " << name << endl;
        return result;
    }
    function<R(Args...)> func;
    string name;
};
Run Code Online (Sandbox Code Playgroud)

我想将以下简单add函数传递给记录器:

int add(int a, int b)
{
    cout<<"Add two value"<<endl;

    return a+b;
}
Run Code Online (Sandbox Code Playgroud)

通过这样调用它:

auto caller = Logger3<int(int,int)>(add,"test");
Run Code Online (Sandbox Code Playgroud)

但是,它会产生以下错误:

error: function returning a function
  133 |     Logger3(function<R(Args...)> func,
      |     ^~~~~~~
decorator.h:138:7: error: function returning a function
  138 |     R operator() (Args ...args)
      |       ^~~~~~~~
decorator.h:145:26: error: function returning a function
  145 |     function<R(Args...)> func;
Run Code Online (Sandbox Code Playgroud)

woh*_*tad 8

您的代码中有3个问题:

  1. Logger3模板需要R是函数的返回值Args(及其参数)。
    R不是您尝试实例化所暗示的函数类型Logger3)。
    因此,Logger3在您的情况下实例化一个获取 2int并返回 an 的函数int应该是:
auto caller = Logger3<int, int, int>(add, "test");
Run Code Online (Sandbox Code Playgroud)
  1. 您的Logger3 构造函数应该是公共的,以便从类外部调用它。

  2. 出于效率原因,您应该使用std::forward将参数转发operator()到您的函数。这将避免参数的复制(在它们的类型比ints 更复杂的情况下更重要)。
    请注意,为了按std::forward预期工作,operator()它本身必须是使用转发引用的可变参数模板(见下文)。

完整修复版本:

auto caller = Logger3<int, int, int>(add, "test");
Run Code Online (Sandbox Code Playgroud)

输出:

Entering test
Add two value
Exiting test
result: 7
Run Code Online (Sandbox Code Playgroud)

演示:Godbolt

旁注:最好避免using namespace std- 请参阅此处:为什么是“using namespace std;” 被认为是不好的做法?


康桓瑋*_*康桓瑋 7

您需要使用模板类部分特化来获取R.

template <typename F>
class Logger3;

template <typename R, typename... Args>
class Logger3<R(Args...)>
{
  // implementation details
};
Run Code Online (Sandbox Code Playgroud)

当您显式指定 时,这会匹配部分特化的int模板参数。RLogger3<int(int,int)>