C++ 指向具有未知参数数的函数的指针是否可能?
我正在编写一个简单的类来度量函数在时间方面的性能。用户应该能够发送一个指向其函数的指针,函数的参数,调用函数的时间,我将调用函数,返回经过的时间。这里我的问题是我不知道用户的函数需要多少参数!我曾想过使用变量函数来获取未知数量的参数,但我仍然有一个问题,即声明用户作为参数传递的函数指针(因为它没有常量变量),并且不知道使用变量函数接收的变量类型 这应该不难,我想:)我想做的就是调用一个函数,这个函数不是我用函数指针定义的C++ 指向具有未知参数数的函数的指针是否可能?,c++,variadic-functions,C++,Variadic Functions,我正在编写一个简单的类来度量函数在时间方面的性能。用户应该能够发送一个指向其函数的指针,函数的参数,调用函数的时间,我将调用函数,返回经过的时间。这里我的问题是我不知道用户的函数需要多少参数!我曾想过使用变量函数来获取未知数量的参数,但我仍然有一个问题,即声明用户作为参数传递的函数指针(因为它没有常量变量),并且不知道使用变量函数接收的变量类型 这应该不难,我想:)我想做的就是调用一个函数,这个函数不是我用函数指针定义的 有什么方法可以解决这些问题吗?或者,让函数指针指向具有未知参数的函数是没有
有什么方法可以解决这些问题吗?或者,让函数指针指向具有未知参数的函数是没有意义的。如果您不知道有多少个参数(更不用说它们的类型了),您将如何在运行时填写这些参数 最好的方法是要求用户的函数都具有相同的原型,即将
va_列表
作为参数,并要求您的库为您的库提供相同的va_列表
(另请参见)
e、 g:
我认为可以使用lambda函数来实现这一点:
template< typename Func >
unsigned int measure(Func f)
{
// take time
f();
// take time
return result;
}
void test_func_1(int i) { std::cout << i; }
void test_func_2(std::ostream& os) { os << 42; }
int main()
{
auto lambda_func_1 = [](){ test_func_1(42); };
const unsigned int time_1 = measure( lambda_func_1 );
std::cout << "calling test_func_1(42) took " << time_1 << " <unit>\n";
auto lambda_func_2 = [](){ test_func_2(std::cerr); };
const unsigned int time_2 = measure( lambda_func_2 );
std::cout << "calling test_func_2(std::cout) took " << time_2 << " <unit>\n";
return 0;
}
模板
无符号整数度量(Func f)
{
//慢慢来
f();
//慢慢来
返回结果;
}
不幸的是,当前的C++要求你写一组长度可变的模板,每个可能的计数都要用一个模板。原则上,C++ 0x允许使用像So:< /P>这样的可变模板。
template<typename Rv, typename Wrapper, typename... Args>
struct impl_wrapper {
std::function<Rv (Args...)> func;
Rv operator()(Args... args) const {
Wrapper w;
return func(args...);
}
impl_wrapper(const std::function<Rv (Args...)> f)
: func(f)
{
}
};
template<typename Wrapper>
struct wrap_func_ {
template<typename Rv, typename... Args>
impl_wrapper<Rv, Args...> operator()(const std::function<Rv (Args...)> &f)
{
return impl_wrapper<Rv, Wrapper, Args...>(f);
}
};
template<typename Wrapper>
static wrap_func_<Wrapper> wrap_func;
struct test_wrapper {
test_wrapper() {
std::cout << "Begin call!\n";
}
~test_wrapper() {
std::cout << "End call!\n";
}
};
int test_call(int x, char *y) {
std::cout << y << x << std::endl;
return x + 1;
}
int main() {
std::function<int (int, char *)> f = test_call;
f = wrap_func<test_wrapper>(f);
std::cout << "Returned: " << f(42, "Prior to increment: ") << std::endl;
return 0;
}
因此,您必须为每个可能的参数计数使用模板重载,直到某个合理的最大值。如果您想要一个不需要可变模板或lambda的解决方案(您必须等待即将发布的标准版本),您可以使用boost::bind
将所有参数预绑定到函数,从而使函数成为不带参数的函数:
#include <boost/bind.hpp>
#include <iostream>
template <typename Func>
int time_call(Func f) {
int start_time = some_get_current_time(); //record the start time
f(); // call the function with no parameters
return some_get_current_time() - start_time; //return the time difference.
};
void my_algorithm(int x, float w, std::string s) {
std::cout << x << w << s << std::endl;
};
int main() {
int time_taken = time_call(boost::bind(&my_algorithm, 42, 0.3, "Hello World!"));
std::cout << "The function took " << time_taken << " time-units to execute!" << std::endl;
return 0;
};
#包括
#包括
模板
int time_调用(函数f){
int start_time=some_get_current_time();//记录开始时间
f();//调用不带参数的函数
返回一些\u get\u current\u time()-start\u time;//返回时差。
};
void my_算法(int x,float w,std::string s){
当OP指定他正在编写一个类时,cout删除了C标记。这是有意义的。您确切地知道调用函数的参数有多少,只是它是一个不同的数字(和不同的类型)对于您想要测量的不同功能。@sbi:是的,但是没有任何有意义的方法可以通过编程来实现。您唯一的选择是透明地转发va_列表
@Oli:有一种方法。请看我的答案。啊,这似乎是我需要的:)非常感谢大家^e我今天在寻找答案时看了一下:)@sbi:是的,我想你的方法是可行的(尽管我从未尝试在C++中使用lambdas),它完全避免了“传递变量数量的参数”(我仍然认为这不是一个有意义的概念!)。我想唯一的问题是OP的编译器是否支持它!我也会尝试一下。度量([](){test_func(42);]);函数调用似乎有点混乱,但可能是因为我还不知道lambda函数:)我现在正在研究它们^lot@Gökay:[](){…}
定义了一个没有参数的匿名类型的函数对象,在调用时执行…
。关闭的]
是我后来修复的一个打字错误。为了减少嵌套括号、括号和大括号的数量,我更改了答案,将lambda函数的创建与对tim的调用分开er函数。:)
啊,是的,我倾向于忘记boost::bind
!Lambda函数非常容易使用和理解,但是如果你还不能使用它们,那么请bind
来解救我!+1
。
test.cpp:21: sorry, unimplemented: cannot expand ‘Args ...’ into a fixed-length argument list
#include <boost/bind.hpp>
#include <iostream>
template <typename Func>
int time_call(Func f) {
int start_time = some_get_current_time(); //record the start time
f(); // call the function with no parameters
return some_get_current_time() - start_time; //return the time difference.
};
void my_algorithm(int x, float w, std::string s) {
std::cout << x << w << s << std::endl;
};
int main() {
int time_taken = time_call(boost::bind(&my_algorithm, 42, 0.3, "Hello World!"));
std::cout << "The function took " << time_taken << " time-units to execute!" << std::endl;
return 0;
};