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;
};