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

4
受Haskell优雅的自动生成(随机)给定类型实例的方式的启发,例如在QuickCheck中,我尝试找出如何在C++中编写一个尽可能易于使用的基准测试框架。我想我将使用函数模板,可能借助C++11中的新功能,例如可变参数模板。我希望只需要指定一个函数或者更好的是函数模板和一个STL模板容器类型(反过来是其value_type),与函数的参数兼容。
我认为,对具有各种大小输入的函数进行基准测试与C++11中设置和生成线程的方式有些相似。我的第一次尝试将是复制thread类的构造函数并将其转换为benchmark函数。
template< class Function, class ...Args >
inline
void benchmark( Function&& f, Args&&... args );

我不确定我们是否应该在这里使用右值引用。然而,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。


1
QuickCheck是一个单元测试库,而不是一个基准测试库... - kennytm
1
如果您对其他解决方案感兴趣,请查看我的C++11 QuickCheck克隆 - John Freeman
1个回答

4

如果您需要支持“高阶参数”,则必须使用模板模板参数。此外,在模板内部,如果没有通过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>);

谢谢。但我仍然会得到一个错误: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()我是这样调用它的:typedef int T; typedef std::vector C; pnw::benchmark_container(); - Nordlöw
绝妙的回答。如果我有更多的星星,我会给你的 ;) - Nordlöw

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接