C++中类似快速检查的模板功能基准测试



受到 Haskell 自动生成给定类型的(随机(实例的优雅方式的启发,例如在 QuickCheck 中,我试图弄清楚如何在C++中编写一个尽可能易于使用的基准测试框架。我想我将使用函数模板,可能会借助 C++11 中的新功能,例如可变参数模板。我的希望是我只需要指定一个函数,甚至更好的函数模板和一个与函数参数兼容的 STL 模板容器类型(反过来又是它的value_type(。

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

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

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

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

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。

如果需要支持"更高种类"的参数,则必须使用模板模板参数。此外,在模板中,如果 typename 不限定,f::g将被视为值。因此,您应该写:

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

最新更新