C ++中类似QuickCheck的模板函数基准测试

时间:2012-01-17 13:23:35

标签: c++ templates testing functional-programming benchmarking

受Haskell优雅的自动生成(随机)实例的启发,例如在QuickCheck中,我试图找出如何编写 as-easy-to-use-as- C ++中可能的基准测试框架。我想我将使用函数模板,可能借助C ++ 11中的新功能,如可变参数模板。我希望我只需要指定一个函数,甚至更好的函数模板和STL模板容器类型(反过来它的value_type)与函数的参数兼容。

我认为,用一组不同大小的输入对函数进行基准测试有点类似于在C ++ 11中设置和生成线程的方式。我的第一次尝试是复制thread类的构造函数并将其转换为benchmark函数

template< class Function, class ...Args >
inline
void benchmark( Function&& f, Args&&... args );

我不确定我们是否应该在这里使用r值refs。但是,必须在调用f之前显式实例化argsbenchmark,从而导致使用繁琐的非功能性

这导致我尝试跳过调用参数,而只使用模板参数:

namespace pnw
{
    template <template <typename> class Function, typename Container>
    inline
    void benchmark_container()
    {
        Function<typename Container::iterator> f;
        Container c(10);
        f(c.begin(), c.end());
    }
}

称为

typedef int T;
typedef std::vector<T> C;
pnw::benchmark_container<std::sort, C>();

但是,编译现在错误为

tests/t_histogram.cpp: In function ‘void test_benchmark()’:
tests/t_histogram.cpp:56:44: error: no matching function for call to ‘benchmark_container()’
tests/t_histogram.cpp:56:44: note: candidate is:
tests/../benchmark.hpp:32:6: note: template<template<class> class Function, class Container> void pnw::benchmark_container()

我不确定C ++是否可以仅通过另一个调用函数的模板参数来处理传递函数模板。

这是正确的方法吗?或者这在C ++ 11中是不可能的?我正在使用GCC-4.6。

1 个答案:

答案 0 :(得分:4)

如果您需要支持“更高级别”参数,则必须使用template-template parameters。此外,在模板内,f::g如果不被typename限定,则会被视为值。因此你应该写:

template <template <typename> class Function, typename Container>  // <--
inline void benchmark_container()
{
    Function<typename Container::iterator> f;   // <--
    ...

(所有这些都在C ++ 11之前可用。)


编辑但是电话

benchmark_container<std::sort, C>();

不起作用,因为std::sort是重载的模板函数,而不是类模板。您也不能单独引用std::sort,因为它不明确。

如果你只想使用没有关联上下文的std::sort之类的函数,你可以传递一个函数指针来消除歧义并使用:

template <typename Container,
          void (*func)(typename Container::iterator, typename Container::iterator)>
inline void benchmark_container()
{
    Container c (10);
    func(c.begin(), c.end());
}

benchmark_container<std::vector<int>, std::sort>();

template <typename Container>
inline void benchmark_container(void (*func)(typename Container::iterator, typename Container::iterator))
{
    Container c (10);
    func(c.begin(), c.end());
}

benchmark_container<std::vector<int>>(std::sort);

或者只是手动选择你想要使用的重载,允许传递一般的函数对象:

template <typename Container, typename F>
inline void benchmark_container(const F& function)
{
    Container c (10);
    function(c.begin(), c.end());
}

benchmark_container<std::vector<int>>(std::sort<std::vector<int>::iterator>);