std::function
invokables, . , ==
, lambdas ==
compariable.
typeid
invokable, false, , , ==
, , , ==
.
" ", " ". , :
using std::shared_ptr<void> token;
template<class...Message>
struct broadcaster {
using listener = std::function<void(Message...)>;
using splistener = std::shared_ptr<listener>;
using wplistener = std::weak_ptr<listener>;
token listen( listener f ) {
auto sf = std::make_shared<listener>(std::move(f));
listeners.push_back(sf);
return sf;
}
std::size_t operator()( Message... message ) const {
targets.erase( std::remove_if( begin(targets), end(targets),
[](auto&& ptr) { return !ptr.lock(); }
), end(targets) );
auto tmp = targets;
for (auto wf : tmp) {
if(auto sf = wf.lock()) {
sf( message... );
}
}
}
private:
mutable std::vector<wplistener> targets;
};
, . , , . std::vector<token>
.
, , .
, , /, moreso. , / (, ), . listen
.
"no lambdas ". , ==
, bob - .
state( some_state... )
([](some_state&&...){
return [&](some_args...){
/* code */
});
, , , , , ==
.
template<class F, class...Args>
struct bound_state {
std::tuple<Args...> state;
F f;
friend bool operator==( bound_state const& lhs, bound_state const& rhs ) {
return lhs.state==rhs.state;
}
template<class...Ts>
decltype(auto) operator()(Ts&&...ts){
return std::apply(f, state)( std::forward<Ts>(ts)... );
}
};
template<class...Args>
auto state( Args&&... args ) {
auto tup = std::make_tuple( std::forward<Args>(args)... );
return [tup=std::move(tup)](auto&& f) {
return bound_state<std::decay_t<decltype(f)>, std::decay_t<Args>...>{
tup, decltype(f)(f)
};
};
}
somesuch.
std::function
. ==
( , ) ( std::function
s).
==
, , typeid, ==
.
template<class Sig>
struct func_with_equal : std::function<Sig> {
using Base = std::function<Sig>;
using Base::operator();
using equality = bool( func_with_equal const&, func_with_equal const& );
equality* pequal = nullptr;
template<class F>
static equality* erase_equality() {
return [](func_with_equal const& lhs, func_with_equal const&rhs)->bool {
assert( lhs.target_type() == rhs.target_type() );
assert( lhs.target_type() == typeid(F) );
return *lhs.target<F>() == *rhs.target<F>();
};
}
friend bool operator==( func_with_equal const& lhs, func_with_equal const& rhs ) {
if (!lhs && !rhs) return true;
if (!lhs || !rhs) return false;
if (lhs.target_type() != rhs.target_type()) return false;
return lhs.pequal( lhs, rhs );
}
};
, , . , .