传递函数模板的地址

时间:2017-05-24 15:47:06

标签: c++ function-templates

考虑以下功能:

template <int node>
void RemainingEnergyTrace (double oldValue, double newValue)
{
  std::stringstream ss;
  ss << "Energy_" << node << ".log";
  static std::fstream f (ss.str().c_str(), std::ios::out);
  f << Simulator::Now().GetSeconds() << "  Remaining energy=" << newValue << std::endl;
}

请注意函数 int node 的模板定义。我尝试在main()中传递此函数的地址:

int inc = 0;  
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));

会产生以下错误:

error: the value of ‘inc’ is not usable in a constant expression
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
                                                                                                      ^
error: no matching function for call to ‘MakeCallback(<unresolved overloaded function type>)’
eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
                                                                                                          ^

但是,以下声明有效:

eSources.Get (0)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<0>));

总之,实际数字有效,但是当以模板格式传递整数变量时,它不会。是因为整数变量必须是 const 类型(如错误所示)?

我试图实际运行一个循环并将函数的地址传递给不同的整数值。我怎样才能做到这一点?

for(int inc = 0; inc<nWifi; inc++)
{
  eSources.Get (inc)->TraceConnectWithoutContext ("RemainingEnergy", MakeCallback(&RemainingEnergyTrace<inc>));
}

1 个答案:

答案 0 :(得分:3)

简而言之,you can't。由于模板在编译时扩展,因此您还需要在编译时提供值。如果nWifi是仅在运行时可用的值,则需要使用常规参数:

void RemainingEnergyTrace (double oldValue, double newValue, int node);

如果您希望创建部分应用的函数以传递给MakeCallback,可以使用lambdas创建它们:

for(int inc = 0; inc<nWifi; inc++)
{
    auto callback = [=](double oldVal, double newVal) {
        RemainingEnergyTrace(oldVal, newVal, inc);
    };
    ...
}

但是这个won't decay to a function pointer,因此您可能需要将MakeCallback API更改为使用std::function(现在这是一种首选方法)或使用附加参数 1 ,或者使用一些库来提供您需要的委托功能。

1 通常,采用函数指针的C或C ++ API也会使用额外的void*参数存储在函数指针旁边。然后,在调用时,指针将被传递给该函数,并存储必要的闭包数据(在您的情况下,它可能指向驻留在内存中某处的inc值)。在不知道MakeCallback如何工作的情况下,无法确定这里最好的解决方案。