diff --git a/ostd/format.hh b/ostd/format.hh index 3cf0888..41760c2 100644 --- a/ostd/format.hh +++ b/ostd/format.hh @@ -887,7 +887,7 @@ namespace detail { return -1; } if (spec.arg_width()) { - if (argpos <= (argprec + 1)) { + if (argpos <= (Size(argprec) + 1)) { assert(false && "argument width not given"); return -1; } diff --git a/ostd/signal.hh b/ostd/signal.hh index b49ed3a..98e83f1 100644 --- a/ostd/signal.hh +++ b/ostd/signal.hh @@ -11,73 +11,119 @@ namespace ostd { +namespace detail { + template + struct EventBase { + EventBase(C *cl): p_class(cl), p_funcs(nullptr), p_nfuncs(0) {} + + EventBase(const EventBase &ev): p_class(ev.p_class), + p_nfuncs(ev.p_nfuncs) { + using Func = Function; + Func *nbuf = (Func *)new byte[sizeof(Func) * p_nfuncs]; + for (Size i = 0; i < p_nfuncs; ++i) + new (&nbuf[i]) Func(ev.p_funcs[i]); + p_funcs = nbuf; + } + + EventBase(EventBase &&ev): p_class(ev.p_class), p_funcs(ev.p_funcs), + p_nfuncs(ev.p_nfuncs) { + ev.p_class = nullptr; + ev.p_funcs = nullptr; + ev.p_nfuncs = 0; + } + + void clear() { + for (Size i = 0; i < p_nfuncs; ++i) + p_funcs[i].~Function(); + delete[] (byte *)p_funcs; + p_funcs = nullptr; + p_nfuncs = 0; + } + + template + Size connect(F &&func) { + using Func = Function; + Func *nbuf = (Func *)new byte[sizeof(Func) * (p_nfuncs + 1)]; + for (Size i = 0; i < p_nfuncs; ++i) { + new (&nbuf[i]) Func(move(p_funcs[i])); + p_funcs[i].~Func(); + } + new (&nbuf[p_nfuncs]) Func(forward(func)); + delete[] (byte *)p_funcs; + p_funcs = nbuf; + return p_nfuncs++; + } + + bool disconnect(Size idx) { + if ((idx >= p_nfuncs) || !p_funcs[idx]) return false; + p_funcs[idx] = nullptr; + return true; + } + + template + void emit(Args &&...args) const { + if (!p_class) return; + for (Size i = 0; i < p_nfuncs; ++i) + if (p_funcs[i]) p_funcs[i](*p_class, args...); + } + + private: + C *p_class; + Function *p_funcs; + Size p_nfuncs; + }; +} /* namespace detail */ + template struct Event { - Event(C *cl = nullptr): p_class(cl), p_funcs(nullptr), p_nfuncs(0) {} +private: + using Base = detail::EventBase; + Base p_base; +public: + Event(C *cl): p_base(cl) {} + Event(const Event &ev): p_base(ev.p_base) {} + Event(Event &&ev): p_base(move(ev.p_base)) {} - Event(const Event &ev): p_class(ev.p_class), p_nfuncs(ev.p_nfuncs) { - using Func = Function; - Func *nbuf = (Func *)new byte[sizeof(Func) * p_nfuncs]; - for (Size i = 0; i < p_nfuncs; ++i) - new (&nbuf[i]) Func(ev.p_funcs[i]); - p_funcs = nbuf; - } + ~Event() { clear(); } - Event(Event &&ev): p_class(ev.p_class), p_funcs(ev.p_funcs), - p_nfuncs(ev.p_nfuncs) { - ev.p_class = nullptr; - ev.p_funcs = nullptr; - ev.p_nfuncs = 0; - } - - ~Event() { - clear(); - } - - void clear() { - for (Size i = 0; i < p_nfuncs; ++i) - p_funcs[i].~Function(); - delete[] (byte *)p_funcs; - p_funcs = nullptr; - p_nfuncs = 0; - } + void clear() { p_base.clear(); } template - Size connect(F func) { - using Func = Function; - Func *nbuf = (Func *)new byte[sizeof(Func) * (p_nfuncs + 1)]; - for (Size i = 0; i < p_nfuncs; ++i) { - new (&nbuf[i]) Func(move(p_funcs[i])); - p_funcs[i].~Func(); - } - new (&nbuf[p_nfuncs]) Func(func); - delete[] (byte *)p_funcs; - p_funcs = nbuf; - return p_nfuncs++; - } + Size connect(F &&func) { return p_base.connect(forward(func)); } - bool disconnect(Size idx) { - if ((idx >= p_nfuncs) || !p_funcs[idx]) return false; - p_funcs[idx] = nullptr; - return true; - } + bool disconnect(Size idx) { return p_base.disconnect(idx); } template - void emit(Args &&...args) const { - if (!p_class) return; - for (Size i = 0; i < p_nfuncs; ++i) - if (p_funcs[i]) p_funcs[i](*p_class, args...); - } + void emit(Args &&...args) { p_base.emit(forward(args)...); } template - void operator()(Args &&...args) const { - emit(forward(args)...); - } + void operator()(Args &&...args) { emit(forward(args)...); } +}; +template +struct Event { private: - C *p_class; - Function *p_funcs; - Size p_nfuncs; + using Base = detail::EventBase; + Base p_base; +public: + Event(C *cl): p_base(cl) {} + Event(const Event &ev): p_base(ev.p_base) {} + Event(Event &&ev): p_base(move(ev.p_base)) {} + + ~Event() { clear(); } + + void clear() { p_base.clear(); } + + template + Size connect(F &&func) { return p_base.connect(forward(func)); } + + bool disconnect(Size idx) { return p_base.disconnect(idx); } + + template + void emit(Args &&...args) const { p_base.emit(forward(args)...); } + + template + void operator()(Args &&...args) const { emit(forward(args)...); } }; } /* namespace ostd */