我有一个类来存储一个函数,当它被调用时它会存储函数的运行时间。 它在void返回类型函数上很好用。但是当我想获得存储函数的返回类型时,我得到了一个'空值不被忽略,因为它应该是'。我无法专门化模板,因为返回类型不是协变的(据我所知)。
所以下面的课很糟糕。
class TimeDurationOperation {
public:
TimeDurationOperation(boost::function<void(void)> operation_)
: operation(operation_) { }
template <typename R> R operate() {
const boost::posix_time::ptime start =
boost::posix_time::microsec_clock::local_time();
R return_value = operation();
const boost::posix_time::ptime stop =
boost::posix_time::microsec_clock::local_time();
elapsed = stop - start;
return return_value;
}
boost::posix_time::time_duration elapsed_time() const {
return elapsed;
}
private:
boost::function<void(void)> operation;
boost::posix_time::time_duration elapsed;
};
工作版本操作()函数:
void operate() {
const boost::posix_time::ptime start =
boost::posix_time::microsec_clock::local_time();
operation();
const boost::posix_time::ptime stop =
boost::posix_time::microsec_clock::local_time();
elapsed = stop - start;
}
我想这样称呼它:
TimeDurationOperation tdo(boost::bind(detail::fun1, 2000));
tdo.operate();
std::cout << tdo.elapsed_time() << std::endl;
和
TimeDurationOperation tdo2(boost::bind(detail::fun2, 500));
int r = tdo2.operate<int>();
std::cout << tdo2.elapsed_time() << " and returned: " << r << std::endl;
你的建议是什么?
答案 0 :(得分:0)
对于类型安全,您将希望TimeDuration知道返回类型。如果它知道参数,它也会更有用:
template<class signature> class TimeDurationOperation;
template<class Ret, class...Params>
class TimeDurationOperation<Ret(Params...) {
public:
TimeDurationOperation(boost::function<Ret(Params...)> operation_)
: operation(operation_) { }
Ret operate(Params... vals) {
const boost::posix_time::ptime start =
boost::posix_time::microsec_clock::local_time();
R return_value = operation(std::forward<Params>(vals)...);
const boost::posix_time::ptime stop =
boost::posix_time::microsec_clock::local_time();
elapsed = stop - start;
return return_value;
}
boost::posix_time::time_duration elapsed_time() const {
return elapsed;
}
private:
boost::function<Ret(Params...)> operation;
boost::posix_time::time_duration elapsed;
};
现在关于实际问题:模板专业化是第一个也是最明显的事情。
template<class...Params>
class TimeDurationOperation<void(Params...) {
public:
TimeDurationOperation(boost::function<void(Params...)> operation_)
: operation(operation_) { }
void operate(Params... vals) {
const boost::posix_time::ptime start =
boost::posix_time::microsec_clock::local_time();
operation(std::forward<Params>(vals)...);
const boost::posix_time::ptime stop =
boost::posix_time::microsec_clock::local_time();
elapsed = stop - start;
}
boost::posix_time::time_duration elapsed_time() const {
return elapsed;
}
private:
boost::function<void(Params...)> operation;
boost::posix_time::time_duration elapsed;
};
或者,(虽然我认为这是一个可怕的想法),人们可能会滥用析构函数。
struct RAII_timer {
RAII_timer(boost::posix_time::time_duration& dest)
: start(boost::posix_time::microsec_clock::local_time())
, elapsed(&dest)
{}
RAII_timer(const RAII_timer& NO_COPIES) = delete;
RAII_timer& operator=(const RAII_timer& NO_COPIES) = delete;
~RAII_timer() {
const boost::posix_time::ptime stop =
boost::posix_time::microsec_clock::local_time();
*elapsed = stop - start;
}
boost::posix_time::ptime start;
boost::posix_time::time_duration* elapsed;
};
Ret operate(Params... vals) {
RAII_timer timer(elapsed);
return operation(std::forward<Params>(vals)...);
}
答案 1 :(得分:0)
好的,所以这篇文章有点旧,但我认为发布答案会有所帮助。
使用现代C ++(11/14)这项任务非常简单。
#include <chrono>
#include <functional>
template <typename Ret, class... Params>
struct TimeDurationOperation {
explicit TimeDurationOperation(std::function<Ret(Params...)> operation)
: operation(operation) { }
template<class R = Ret>
typename std::enable_if<!std::is_void<R>::value, R>::type operate(Params... vals) {
auto start = std::chrono::system_clock::now();
R return_value(operation(std::forward<Params>(vals)...));
auto stop = std::chrono::system_clock::now();
elapsed = stop - start;
return return_value;
}
template<class R = Ret>
typename std::enable_if<std::is_void<R>::value, void>::type operate(Params... vals) {
auto start = std::chrono::system_clock::now();
operation(std::forward<Params>(vals)...);
auto stop = std::chrono::system_clock::now();
elapsed = stop - start;
}
const std::chrono::duration<double>& elapsed_time() const {
return elapsed;
}
private:
std::function<Ret(Params...)> operation;
std::chrono::duration<double> elapsed;
};
您可以通过以下方式使用此方法:
int return_test_function(int i) {
std::this_thread::sleep_for(20ms);
return i * 2;
}
TimeDurationOperation<int, int> tdo(return_test_function);
auto result = tdo.operate(21);
auto elapsed = static_cast<double>(duration_cast<milliseconds(tdo.elapsed_time()).count());
使用可变参数模板,您可以表示任何参数列表。 使用std :: function,您可以表示任何功能。简单函数(指针)隐式转换为此类型。 使用std :: enable_if进行SFINAE实现。如果enable_if中的表达式为false,则不编译该函数。尝试使用&#34;错误&#34;带模板的函数将导致编译器错误(或警告,具体取决于编译器)。 您可以使用std :: chrono测量已用时间。
注意:此解决方案仅使用标准。不需要第三方库(如Boost)。