受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
之前显式实例化args
和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。
答案 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>);