2017-05-24 91 views
2

考慮下面的函數的地址:傳遞函數模板

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節點的模板定義。我試圖通過這個函數的地址在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

什麼是'MakeCallback'? –

回答

3

總之,you can't。由於模板在編譯時展開,因此您還需要在編譯時提供這些值。如果nWifi的是,只有在運行時可用的值,則需要使用常規的參數:

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

如果你想然後創建部分應用功能傳遞給你的MakeCallback,你可以使用lambda表達式創建它們:

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(這是現在的首選方法)或採取其他參數,或者使用某些庫來提供所需的委託功能。


典型地,需要函數指針C或C++ API也將採取額外void*參數來存儲函數指針旁邊。然後,在調用時,指針將被傳遞給該函數,並存儲必要的閉包數據(在您的情況下,它可能指向駐留在內存某處的inc值)。在不知道MakeCallback是如何工作的情況下,不可能說出什麼是最好的解決方案。

相關問題