[英]Passing functions as arguments in C++
我對 C++ 有點生疏,在使用了一年的 python 后我要切換了。 自然地,我想將來自 python 的懶惰轉化為 C++。
我剛剛發現了 rot13,我對此感到非常興奮。 我找到了 3 種方法,我想做一些性能測試。 我還想看看在原地修改字符串或創建一個新字符串是否有區別。 所以我最終得到了 6 個函數。
在第一種方法中,我使用 std::map 來映射字符,因此我構建了一個初始化映射的類,在第二種方法中我使用了三元運算符,第三種我使用了位移。
現在函數原型看起來像這樣
// map dependent
void Rot13::convert_inplace(string& mystr){
string Rot13::convert(const string& mystr){
// ternary operator
void bitrot_inplace(string& mystr){
string bitrot(const string& mystr){
// bit shift
void bitshiftrot_inplace(string& mystr){
string bitshiftrot(const string& mystr){
我想構建一個接受這些函數作為參數的函數,然后計算時間並打印結果
所以我查看了 stackoverflow, 1 , 2 ,然后我想出了這個
typedef void (*vfc)(string str);
void printtime_inplace(string title, vfc func){
我嘗試了這種構造,但這意味着我受到vfc
返回類型的限制,在我的情況下它是void
或string
,並且我需要傳遞類的指針。 因此,我將不得不做 3 個函數來適應不同的函數,即類成員函數的函數、void 返回類型的函數和字符串返回類型的函數。
於是我問自己,我真的需要使用模板來不寫3次相同的函數嗎? 我真的對模板沒有信心,但我應該做 3 個typedefs
並構造 printtime 函數以接受模板嗎? 此外,有沒有辦法告訴模板您將只接受這些類型(即我定義的類型)?
另一個問題,這是一個好的設計嗎? 或者你會建議其他設計嗎? 另一個實現?
IMO,最簡單的方法是使用模板而不是嘗試編寫具有具體類型的函數。
template<typename Function>
void printtime_inplace(string title, Function func)
{
//...
func(title);
//...
}
這現在將允許您采取任何“功能”。 您可以向它傳遞一個常規函數、一個函子、一個 lambda、一個std::function
,基本上,任何可調用的。 編譯器將為您消除不同的實例化,但就您的代碼而言,您正在調用相同的函數。
您可以使用std::function
來提供這樣的模板:
#include <iostream>
#include <functional>
#include <string>
#include <type_traits>
void convert_inplace(std::string& mystr){}
std::string convert(const std::string& mystr){
return mystr;
}
void bitrot_inplace(std::string& mystr){}
template<typename ret, typename par>
using fn = std::function<ret(par)>;
template<typename ret, typename par>
void caller(fn<ret,par> f) {
typename std::remove_reference<par>::type p;
ret r = f(p);
}
template<typename par>
void caller(fn<void,par> f) {
typename std::remove_reference<par>::type p;
f(p);
}
int main() {
auto f1 = fn<void,std::string&>(convert_inplace);
auto f2 = fn<std::string,const std::string&>(convert);
auto f3 = fn<void,std::string&>(bitrot_inplace);
caller(f1);
caller(f2);
caller(f3);
return 0;
}
請參閱現場演示。
如果你想要一個帶有可變參數的函數,這里有一個基於 user0042s 答案的例子(另見https://github.com/goblinhack/c-plus-plus-examples/blob/master/std_function_with_variadic_template/README.md )
#include <iostream>
int my_wrapped_function (int x, const std::string y)
{
std::cout << "SUCCESS: Hello from my_wrapped_function(x=" << x << ", y=" << y << ");" << std::endl;
return 43;
}
void my_argument_modifier (int &x)
{
std::cout << "SUCCESS: Hello from my_argument_modifier(x=" << x << ") => " << x + 1 << ";" << std::endl;
x++;
}
template<typename ret, typename T, typename... Rest>
using fn = std::function<ret(T, Rest...)>;
template<typename ret, typename T, typename... Rest>
ret wrapper(fn<ret, T, Rest...> f, T t, Rest... rest)
{
return f(t, rest...);
}
template<typename ret, typename T, typename... Rest>
ret wrapper(fn<ret, T&, Rest&...> f, T& t, Rest&... rest)
{
return f(t, rest...);
}
int main()
{
// Wrap a function with variable arguments
auto f1 = fn<int,int,const std::string>(my_wrapped_function);
auto result = wrapper(f1, 42, std::string("hello"));
// Result should be 43:
// Wrap a function that modifies its arguments
auto f2 = fn<void,int&>(my_argument_modifier);
wrapper(f2, result);
// Result should be 44:
return 0;
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.