C++ 11에서는 모든 것이 필요한만큼 간단합니다. 타이머를 구현하십시오.
바운드 함수 호출을 전달하는 가장 간결한 방법은 람다 구문을 사용하여 생성 된 펑터를 전달하는 것입니다 (예 : []{ std::cout << "Hello, world!" << std::endl; }
).이렇게 생성 된 객체는 컴파일러에만 알려진 유형이지만 유형은 std::function<void()>
으로 변환됩니다.
#include <functional>
#include <list>
#include <chrono>
#include <thread>
#include <iostream>
template <typename Clock = std::chrono::high_resolution_clock>
class Timers {
public:
using clock = Clock;
using duration = typename clock::duration;
using time_point = typename clock::time_point;
private:
struct Timer {
duration const period;
std::function<void()> const call;
int repeats;
time_point next;
Timer(duration $period, int $repeats, std::function<void()> && $call) :
period($period), call(std::move($call)), repeats($repeats) {}
};
std::list<Timer> m_timers;
public:
Timers() {}
Timers(const Timers &) = delete;
Timers & operator=(const Timers &) = delete;
template <typename C> void add(std::chrono::milliseconds period,
int repeats, C && callable)
{
if (repeats) m_timers.push_back(Timer(period, repeats, callable));
}
enum class Missed { Skip, Emit };
void run(Missed missed = Missed::Emit) {
for (auto & timer : m_timers) timer.next = clock::now() + timer.period;
while (! m_timers.empty()) {
auto next = time_point::max();
auto ti = std::begin(m_timers);
while (ti != std::end(m_timers)) {
while (ti->next <= clock::now()) {
ti->call();
if (--ti->repeats <= 0) {
ti = m_timers.erase(ti);
continue;
}
do {
ti->next += ti->period;
} while (missed == Missed::Skip && ti->next <= clock::now());
}
next = std::min(next, ti->next);
++ ti;
}
if (! m_timers.empty()) std::this_thread::sleep_until(next);
}
}
};
int main(void)
{
Timers<> timers;
using ms = std::chrono::milliseconds;
timers.add(ms(1000), 2, []{ std::cout << "Hello, world!" << std::endl; });
timers.add(ms(100), 20, []{ std::cout << "*" << std::endl; });
timers.run();
std::cout << std::endl;
return 0;
}
은 void 함수를 호출합니까? – Ninja
@ 닌자 물론 그렇습니다. 호출자는 반환 유형이 무엇인지 모르는 경우 함수를 어떻게 사용할 수 있습니까? 당신은'boost :: function'을 사용하고 리턴 타입을 원하는 것으로 캐스팅 할 수있다. 현대적인 C++ 대안을 원한다면'boost :: function '을 사용하여 어떤 형식의 삭제로 재생할 수 있습니다. –
kizzx2