Boost MSM process_event doesn't transit between SM states - c++

I've created a HSM using boost MSM.
Diagram:
Code:
#include <boost/msm/back/state_machine.hpp>
#include <boost/msm/back/tools.hpp>
#include <boost/msm/front/euml/operator.hpp>
#include <boost/msm/front/state_machine_def.hpp>
#include <boost/msm/front/functor_row.hpp>
// TODO - move this from here to different module
struct EventConfigure {};
struct EventSendDetailsRsp {};
struct EventSendGrantsRsp {};
struct EventGetGrantsRsp {};
struct EventGetStatsRsp {};
struct EventCycleTimeout {};
struct EventStartWaitTimerExpired {};
struct EventGapTimerExpired {};
// ---------------------- CYCLING STATE MACHINE----------------------//
/* Internal Cycling SM */
struct CyclingSm_
: msmf::state_machine_def<CyclingSm_> {
CyclingSm_() {}
struct FillingDetails : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "FillingDetails::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "FillingDetails::on_exit");
}
};
struct SendingGrants : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "SendingGrants::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "SendingGrants::on_exit");
}
};
struct GettingGrants : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "GettingGrants::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "GettingGrants::on_exit");
}
};
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "CyclingSm::on_entry");
// Need to prepare here the next cycle (cms_groups)
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "CyclingSm::on_exit");
}
struct PseudoCycleExit : public msmf::exit_pseudo_state<msmf::none> {};
typedef FillingDetails initial_state;
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +-------------------------------+-----------------------------+----------------------------------+----------------------------------------------+----------+
msmf::Row<FillingDetails, EventSendDetailsRsp, SendingGrants, msmf::none, msmf::none>,
// +-------------------------------+-----------------------------+----------------------------------+-----------------------------------------------+----------+
msmf::Row<SendingGrants, EventSendGrantsRsp, GettingGrants, msmf::none, msmf::none>,
// +-------------------------------+-----------------------------+----------------------------------+------------------------------------------------+----------+
msmf::Row<GettingGrants, EventGetGrantsRsp, PseudoCycleExit, msmf::none, msmf::none>
>, OBJECTS_COUNTER(transition_table) {};
template<class Fsm, class Event>
void no_transition(Event const& e, Fsm& rFsm, int state)
{
typedef typename Fsm::stt Stt;
typedef typename msm::back::generate_state_set<Stt>::type all_states; //all states
std::string state_name;
// fill state_name for state
boost::mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
(msm::back::get_state_name<Stt>(state_name, state));
LOG4CXX_WARN(Logger(), "no_transition from state " << state_name << " by event " << typeid(e).name());
}
template <class Fsm, class Event>
void exception_caught (Event const& event, Fsm& rFsm, const std::exception& e)
{
LOG4CXX_ERROR(Logger(), " exception_caught: " << e.what() <<" by event " << typeid(event).name());
}
}; // CyclingSm_
typedef msm::back::state_machine<CyclingSm_> CyclingSm;
// ----------------- OUTER STATE MACHINE ---------------//
struct OuterSm_
: msmf::state_machine_def<OuterSm_> {
OuterSm_() {}
struct StateStandby : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "StateStandby::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "StateStandby::on_exit");
}
};
struct StateStartWaiting : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "StateStartWaiting::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "StateStartWaiting::on_exit");
}
};
// ---------------------- OPERATIONAL STATE MACHINE----------------------//
struct OperationalSm_ : msmf::state_machine_def<OperationalSm_> {
OperationalSm_() {}
struct GettingStats : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "GettingStats::on_entry");
}
template <class Fsm>
void on_exit(const EventGetStatsRsp& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "GettingStats::on_exit (EventGetStatsRsp)");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "GettingStats::on_exit");
}
};
struct GapWaiting : msmf::state<> {
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "GapWaiting::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "GapWaiting::on_exit");
}
};
template <class Event, class Fsm>
void on_entry(const Event& rEvent, Fsm& rFsm) const
{
// add here name maybe
LOG4CXX_INFO(Logger(), "Operational::on_entry");
}
template <class Event, class Fsm>
void on_exit(const Event& rEvent, Fsm& rFsm) const
{
LOG4CXX_INFO(Logger(), "Operational::on_exit");
}
struct GuardStatsTimerExpired {
template <class Event, class Fsm, class SRC, class DST>
bool operator()(const Event& rEvent, const Fsm& rFsm, const SRC&, const DST&)
{
LOG4CXX_INFO(Logger(), "GuardStatsTimerExpired");
return true;
}
};
// Struct defining cycling sub-state
struct Cycling : CyclingSm {
Cycling() : CyclingSm() {}
};
typedef GettingStats initial_state;
struct transition_table:mpl::vector<
// Start Event Next Action Guard
// +------------------------------------+------------------------------+-----------------------+----------------+---------+
msmf::Row<Cycling::exit_pt
<Cycling::PseudoCycleExit>, msmf::none, GapWaiting, msmf::none, msmf::none>,
msmf::Row<GapWaiting, EventGapTimerExpired, GettingStats, msmf::none, GuardStatsTimerExpired>,
msmf::Row<GapWaiting, EventGapTimerExpired, CyclingSm, msmf::none, msmf::none>,
msmf::Row<GettingStats, EventGetStatsRsp, CyclingSm, msmf::none, msmf::none>
>, OBJECTS_COUNTER(transition_table) {};
template<class Fsm, class Event>
void no_transition(Event const& e, Fsm& rFsm, int state)
{
typedef typename Fsm::stt Stt;
typedef typename msm::back::generate_state_set<Stt>::type all_states; //all states
std::string state_name;
// fill state_name for state
boost::mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
(msm::back::get_state_name<Stt>(state_name, state));
LOG4CXX_WARN(Logger(), "no_transition from state "
<< state_name << " by event "
<< typeid(e).name());
}
template <class Fsm, class Event>
void exception_caught (Event const& event, Fsm& rFsm, const std::exception& e)
{
LOG4CXX_ERROR(Logger(), " exception_caught: " << e.what() <<" by event " << typeid(event).name());
}
}; // OperationalSm_
typedef msm::back::state_machine<OperationalSm_> OperationalSm;
struct GuardEnabled {
template <class Event, class Fsm, class SRC, class DST>
bool operator()(const Event& rEvent, Fsm& rFsm, SRC&, DST&) const
{
LOG4CXX_INFO(Logger(), "GuardEnabled");
return true;
}
};
struct GuardWithinCurrentCycleInterval {
template <class Event, class Fsm, class SRC, class DST>
bool operator()(const Event& rEvent, Fsm& rFsm, SRC&, DST&)
{
LOG4CXX_INFO(Logger(), "GuardWithinCurrentCycleInterval");
return true;
}
};
struct GuardWithinFutureCycleInterval {
template <class Event, class Fsm, class SRC, class DST>
bool operator()(const Event& rEvent, Fsm& rFsm, SRC&, DST&)
{
LOG4CXX_INFO(Logger(), "GuardWithinFutureCycleInterval");
return false;
}
};
using GuardIsEnabledAndWithinCurrentCyclingInterval = msmf::euml::And_<GuardEnabled, GuardWithinCurrentCycleInterval>;
using GuardIsEnabledAndWithinFutureCyclingInterval = msmf::euml::And_<GuardEnabled, GuardWithinFutureCycleInterval>;
typedef StateStandby initial_state;
struct transition_table : mpl::vector<
// Start Event Next Action Guard
// +----------------------------------+---------------------------+----------------------------------+-----------------+----------+
msmf::Row<StateStandby, EventConfigure, OperationalSm, msmf::none, GuardIsEnabledAndWithinCurrentCyclingInterval>,
msmf::Row<StateStandby, EventConfigure, StateStartWaiting, msmf::none, GuardIsEnabledAndWithinFutureCyclingInterval>,
msmf::Row<StateStandby, EventConfigure, msmf::none, msmf::none, msmf::none>,
// +----------------------------------+-------------------------+---------------------------------+--------------------+----------+
msmf::Row<StateStartWaiting, EventConfigure, OperationalSm, msmf::none, GuardIsEnabledAndWithinCurrentCyclingInterval>,
msmf::Row<StateStartWaiting, EventConfigure, msmf::none, msmf::none, GuardIsEnabledAndWithinFutureCyclingInterval>,
msmf::Row<StateStartWaiting, EventConfigure, StateStandby, msmf::none, msmf::none>,
msmf::Row<StateStartWaiting, EventStartWaitTimerExpired, OperationalSm, msmf::none, msmf::none>,
// +----------------------------------+-------------------------+---------------------------------+--------------------+----------+
msmf::Row<OperationalSm, EventConfigure, msmf::none, msmf::none, GuardIsEnabledAndWithinCurrentCyclingInterval>,
msmf::Row<OperationalSm, EventConfigure, StateStartWaiting, msmf::none, GuardIsEnabledAndWithinFutureCyclingInterval>,
msmf::Row<OperationalSm, EventConfigure, StateStandby, msmf::none, msmf::none>,
msmf::Row<OperationalSm, EventCycleTimeout, msmf::none, msmf::none, GuardIsEnabledAndWithinCurrentCyclingInterval>,
msmf::Row<OperationalSm, EventCycleTimeout, StateStartWaiting, msmf::none, GuardIsEnabledAndWithinFutureCyclingInterval>,
msmf::Row<OperationalSm, EventCycleTimeout, StateStandby, msmf::none, msmf::none>
// +----------------------------------+-------------------------+---------------------------------+--------------------+----------+
>, OBJECTS_COUNTER(transition_table) {};
template<class Fsm, class Event>
void no_transition(Event const& e, Fsm& rFsm, int state)
{
typedef typename Fsm::stt Stt;
typedef typename msm::back::generate_state_set<Stt>::type all_states; //all states
std::string state_name;
// fill state_name for state
boost::mpl::for_each<all_states,boost::msm::wrap<mpl::placeholders::_1> >
(msm::back::get_state_name<Stt>(state_name, state));
LOG4CXX_INFO(Logger(), "no_transition from state "
<< state_name << " by event "
<< typeid(e).name());
}
template <class Fsm, class Event>
void exception_caught (Event const& event, Fsm& rFsm, const std::exception& e)
{
LOG4CXX_ERROR(Logger(), " exception_caught: " << e.what() <<" by event " << typeid(event).name());
}
}; // OuterSm_
typedef msm::back::state_machine<OuterSm_> OuterSm;
typedef OuterSm::stt Stt;
typedef msm::back::generate_state_set<Stt>::type all_states;
I've created a small unit test just to check that basic transition works with the guard.
int main() {
/// State machine
OuterSm sm;
sm.start();
LOG4CXX_INFO(Logger(), "current state: " << *sm_.current_state());
auto res = sm.process_event(EventConfigure());
LOG4CXX_INFO(Logger(), "process result: " << res);
LOG4CXX_INFO(Logger(), "current state: " << *sm_.current_state());
return 0;
}
Which output is:
4 [0x7faaa5996380] INFO staticLogger null - StateStandby::on_entry
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - current state: 0
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - process result: 1
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - current state: 0
4 [0x7faaa5996380] INFO staticLogger null - StateStandby::on_exit
Meaning somehow my event was processed but there was no transition actually made from StateStandby to OperationalSm.
I've saw this comment:
Boost MSM only processing internal transitions
But I assume it is not relevant to my case because I've created two tuple of guards (And) which one of them will always return false and other return always true.
Is there something I'm missing here that should be done in order the outerSm to invoke OperationalSm (initial state) and other transitions to work as needed?

I've found out that I created the same issue as in:
Boost MSM only processing internal transitions
By adding redundant (empty) transition into transition_table:
msmf::Row<StateStandby, EventConfigure, msmf::none, msmf::none, msmf::none>,
When I removed it and left with (first part of the OuterSm transition):
msmf::Row<StateStandby, EventConfigure, OperationalSm, msmf::none, GuardIsEnabledAndWithinCurrentCyclingInterval>,
msmf::Row<StateStandby, EventConfigure, StateStartWaiting, msmf::none, GuardIsEnabledAndWithinFutureCyclingInterval>
I see the following output:
4 [0x7faaa5996380] INFO staticLogger null - StateStandby::on_entry
4 [0x7faaa5996380] INFO mainLogger:0x1000000:0 null - current state: 0
4 [0x7fc282a66380] INFO staticLogger null - GuardConfigCanBeUsed
4 [0x7fc282a66380] INFO staticLogger null - GuardWithinFutureCycleInterval
4 [0x7fc282a66380] INFO staticLogger null - GuardConfigCanBeUsed
4 [0x7fc282a66380] INFO staticLogger null - GuardWithinCurrentCycleInterval
4 [0x7fc282a66380] INFO staticLogger null - StateStandby::on_exit
4 [0x7fc282a66380] INFO staticLogger null - Operational::on_entry
4 [0x7fc282a66380] INFO staticLogger null - GettingStats::on_entry
As I was expected to see.

Related

C++ Trying to call a method with class that is derived from other class

Hi so I recently tried to create sort of a Filters for a Database which must meet specific Criteria. I am sort of a amateur when it comes to C++ Polymorfism. So I really don't know Where is problem anymore.
Kriterium.h Header ->
//Kriterium.h
#pragma once
#include "Uzemna_Jednotka.h"
#include "Politicke_Strany.h"
template <typename O, typename T>
class Kriterium
{
public:
Kriterium() {};
virtual T ohodnot( O& pObject) = 0;
virtual ~Kriterium() {};
};
template <typename T>
class KriteriumUJ : public Kriterium<Uzemna_Jednotka, T> {
public:
KriteriumUJ() {};
virtual T ohodnot( Uzemna_Jednotka& pJednotka) = 0;
virtual ~KriteriumUJ() {};
};
class KriteriumPatriDo : public KriteriumUJ<bool> {
public:
KriteriumPatriDo() : KriteriumUJ() {};
bool ohodnot( Uzemna_Jednotka& pJednotka) override { return pJednotka.checkIFPatriDoVUC(aVyssiCelok); };
void setVyssiCelok(Uzemna_Jednotka* pJednotka) { aVyssiCelok = pJednotka; };
Uzemna_Jednotka* getVyssiCelok() { return aVyssiCelok; };
~KriteriumPatriDo() {};
private:
Uzemna_Jednotka* aVyssiCelok;
};
Filter.h Header ->
//Filter
#pragma once
#include "Kriterium.h"
#include "Uzemna_Jednotka.h"
#include "structures/heap_monitor.h"
#include "structures/table/sorted_sequence_table.h"
#include "structures/table/unsorted_sequence_table.h"
template<typename O, typename T, typename H>
class Filter
{
public:
Filter() {};
virtual UnsortedSequenceTable<H, O> vyfiltruj(UnsortedSequenceTable<H, O> pVstup, Kriterium<O, T>& pKriterium) = 0;
protected:
virtual bool splnaFilter(O& pObject, Kriterium<O,T>& pKriterium) = 0;
private:
};
template<typename O, typename T, typename H>
class Filter_fi : public Filter<O, T, H>
{
public:
Filter_fi() {};
void setAlpha(T pAlpha) { alphaPARAM = pAlpha; };
T getAlpha() { return alphaPARAM; };
UnsortedSequenceTable<H, O> vyfiltruj(UnsortedSequenceTable<H, O> pVstup, Kriterium<O, T>& pKriterium) override
{
UnsortedSequenceTable<H, O>* table = new UnsortedSequenceTable<H, O>;
for (TableItem<H, O>* prem : pVstup) {
if (splnaFilter(prem->accessData(), pKriterium)) {
table->insert(prem->getKey(), prem->accessData());
}
}
return *table;
};
virtual ~Filter_fi() {};
protected:
virtual bool splnaFilter(O& pObject, Kriterium<O, T>& pKriterium) override { return pKriterium.ohodnot(pObject) == alphaPARAM; };
private:
T alphaPARAM;
};
template<typename O, typename T, typename H>
class Filter_FI : public Filter<O, T, H>
{
public:
Filter_FI() {};
void setParametre(T pMin, T pMax) { aMin = pMin, aMax = pMax; };
T getMin() { return aMin; };
T getMax() { return aMax; };
UnsortedSequenceTable<H, O> vyfiltruj(UnsortedSequenceTable<H, O> pVstup, Kriterium<O, T>& pKriterium) override
{
UnsortedSequenceTable<H, O>* table = new UnsortedSequenceTable<H, O>;
for (TableItem<H, O>* prem : pVstup) {
if (splnaFilter(prem->accessData(), pKriterium)) {
table->insert(prem->getKey(), prem->accessData());
}
}
return *table;
};
virtual ~Filter_FI() {};
protected:
virtual bool splnaFilter(O& pObject, Kriterium<O, T>& pKriterium) override {
T hodnota = pKriterium.ohodnot(pObject);
return (aMin <= hodnota && hodnota <= aMax);
};
//Kriterium<O, T>* aKriterium;
private:
T aMin;
T aMax;
};
class Filter_UJ_Prislusnost : public Filter_fi <Uzemna_Jednotka*, bool, int> {
public:
Filter_UJ_Prislusnost(): Filter_fi() {};
virtual ~Filter_UJ_Prislusnost() {};
};
*The problem is if I try to call ->
aFilter_Typ.setAlpha(UzemnaJednotka_TYP_Enum::Obec);
aFilter_Typ.vyfiltruj(aTabulkaUJ, aKriterium);
-> aKriterium gives a
C++ a reference of type (not const-qualified) cannot be initialized with a value of type
[![Description of the Error][1]][1]
Filter and Kriterium are initialized like this ->
Filter_UJ_Name aFilter_Meno;
KriteriumPatriDo aKriterium;
I would be very glad if you could help me fix the problem.*

(C++) Calling Function From Class Passed By Parameter

I recently stumbled upon a interesting problem. The problem is, in the clas Filter, i don't have any problem calling getKriterium().ohodnot().
But when I want to call it in for example Filter_FI(), it doesn't work.
class Filter
{
public:
Filter() {};
SortedSequenceTable<H, O> vyfiltruj(SortedSequenceTable<H, O> pVstup) {
for (TableItem<H, O> *prem : pVstup) {
if (splnaKriterium(O)) {
table.insert(O);
}
}
return table;
}
virtual ~Filter() {};
void setKriterium(Kriterium<O, T>* pKriterium) { aKriterium = pKriterium; };
Kriterium<O, T>* getKriterium() { return aKriterium; };
protected:
virtual bool splnaFilter(const O& pObject, Kriterium<O, T>& pKrit) = 0;
private:
Kriterium<O, T>* aKriterium;
SortedSequenceTable<T, O>* table;
};
template<typename O, typename T, typename H>
class Filter_fi : public Filter<O, T, H>
{
public:
Filter_fi() {};
void setAlpha(T pAlpha) { alphaPARAM = pAlpha; };
T getAlpha() { return alphaPARAM; };
void test() {
getKriterium().ohodnot()// Here I want to call the function .ohodnot(), But it will not let me...
}
virtual ~Filter_fi() {};
protected:
virtual bool splnaFilter(const O& pObject) override { return (alphaPARAM); };
private:
T alphaPARAM;
};
I would be very glad if you could help me fix the problem.

Impossibly fast Delegate in C++11 on MSVC++14

The Problem
This question relates to several questions about function pointers here (I will not list them), but most importantly it concerns the code posted here. The post claims the code should be standard compliant and it compiles on Apple Clang just fine.
I have not managed to compile it in VS2015, i.e. MSVC++14.
What could be the source of this error and why not with Clang?
First Error
First error repeats multiple times:
...\Delegate.hpp(329): error C2514: 'Delegate<R(A...)>::is_member_pair<<unnamed-symbol>>':
class has no constructors
And the same for is_member_pair_const. It relates to the following part of the code:
template <typename T>
static typename ::std::enable_if<
!(is_member_pair<T>{} ||
is_const_member_pair<T>{}),
R>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
}
Second Error
Multiple errors appear, but the first is usually most important:
...\Delegate.hpp(340): error C2059: syntax error: '<end Parse>'
...\Delegate.hpp(349): note: see reference to class template instantiation 'Delegate<R(A...)>' being compiled
Then follow a few syntax errors, unrecognizable template declaration/definition etc. The code in question:
template <typename T>
static typename ::std::enable_if<
is_member_pair<T>{} ||
is_const_member_pair<T>{},
R
>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (static_cast<T*>(object_ptr)->first->*
static_cast<T*>(object_ptr)->second)(::std::forward<A>(args)...);
}
For Completeness: The entire Delegate.hpp:
Code Source and Base Article
#pragma once
#ifndef DELEGATE_HPP
#define DELEGATE_HPP
#include <cassert>
#include <memory>
#include <new>
#include <type_traits>
#include <utility>
template <typename T> class Delegate;
template<class R, class ...A>
class Delegate<R (A...)>
{
using stub_ptr_type = R (*)(void*, A&&...);
Delegate(void* const o, stub_ptr_type const m) noexcept :
object_ptr_(o),
stub_ptr_(m)
{
}
public:
Delegate() = default;
Delegate(Delegate const&) = default;
Delegate(Delegate&&) = default;
Delegate(::std::nullptr_t const) noexcept : Delegate() { }
template <class C, typename =
typename ::std::enable_if< ::std::is_class<C>{}>::type>
explicit Delegate(C const* const o) noexcept :
object_ptr_(const_cast<C*>(o))
{
}
template <class C, typename =
typename ::std::enable_if< ::std::is_class<C>{}>::type>
explicit Delegate(C const& o) noexcept :
object_ptr_(const_cast<C*>(&o))
{
}
template <class C>
Delegate(C* const object_ptr, R (C::* const method_ptr)(A...))
{
*this = from(object_ptr, method_ptr);
}
template <class C>
Delegate(C* const object_ptr, R (C::* const method_ptr)(A...) const)
{
*this = from(object_ptr, method_ptr);
}
template <class C>
Delegate(C& object, R (C::* const method_ptr)(A...))
{
*this = from(object, method_ptr);
}
template <class C>
Delegate(C const& object, R (C::* const method_ptr)(A...) const)
{
*this = from(object, method_ptr);
}
template <
typename T,
typename = typename ::std::enable_if<
!::std::is_same<Delegate, typename ::std::decay<T>::type>{}
>::type
>
Delegate(T&& f) :
store_(operator new(sizeof(typename ::std::decay<T>::type)),
functor_deleter<typename ::std::decay<T>::type>),
store_size_(sizeof(typename ::std::decay<T>::type))
{
using functor_type = typename ::std::decay<T>::type;
new (store_.get()) functor_type(::std::forward<T>(f));
object_ptr_ = store_.get();
stub_ptr_ = functor_stub<functor_type>;
deleter_ = deleter_stub<functor_type>;
}
Delegate& operator=(Delegate const&) = default;
Delegate& operator=(Delegate&&) = default;
template <class C>
Delegate& operator=(R (C::* const rhs)(A...))
{
return *this = from(static_cast<C*>(object_ptr_), rhs);
}
template <class C>
Delegate& operator=(R (C::* const rhs)(A...) const)
{
return *this = from(static_cast<C const*>(object_ptr_), rhs);
}
template <
typename T,
typename = typename ::std::enable_if<
!::std::is_same<Delegate, typename ::std::decay<T>::type>{}
>::type
>
Delegate& operator=(T&& f)
{
using functor_type = typename ::std::decay<T>::type;
if ((sizeof(functor_type) > store_size_) || !store_.unique())
{
store_.reset(operator new(sizeof(functor_type)),
functor_deleter<functor_type>);
store_size_ = sizeof(functor_type);
}
else
{
deleter_(store_.get());
}
new (store_.get()) functor_type(::std::forward<T>(f));
object_ptr_ = store_.get();
stub_ptr_ = functor_stub<functor_type>;
deleter_ = deleter_stub<functor_type>;
return *this;
}
template <R (* const function_ptr)(A...)>
static Delegate from() noexcept
{
return { nullptr, function_stub<function_ptr> };
}
template <class C, R (C::* const method_ptr)(A...)>
static Delegate from(C* const object_ptr) noexcept
{
return { object_ptr, method_stub<C, method_ptr> };
}
template <class C, R (C::* const method_ptr)(A...) const>
static Delegate from(C const* const object_ptr) noexcept
{
return { const_cast<C*>(object_ptr), const_method_stub<C, method_ptr> };
}
template <class C, R (C::* const method_ptr)(A...)>
static Delegate from(C& object) noexcept
{
return { &object, method_stub<C, method_ptr> };
}
template <class C, R (C::* const method_ptr)(A...) const>
static Delegate from(C const& object) noexcept
{
return { const_cast<C*>(&object), const_method_stub<C, method_ptr> };
}
template <typename T>
static Delegate from(T&& f)
{
return ::std::forward<T>(f);
}
static Delegate from(R (* const function_ptr)(A...))
{
return function_ptr;
}
template <class C>
using member_pair =
::std::pair<C* const, R (C::* const)(A...)>;
template <class C>
using const_member_pair =
::std::pair<C const* const, R (C::* const)(A...) const>;
template <class C>
static Delegate from(C* const object_ptr,
R (C::* const method_ptr)(A...))
{
return member_pair<C>(object_ptr, method_ptr);
}
template <class C>
static Delegate from(C const* const object_ptr,
R (C::* const method_ptr)(A...) const)
{
return const_member_pair<C>(object_ptr, method_ptr);
}
template <class C>
static Delegate from(C& object, R (C::* const method_ptr)(A...))
{
return member_pair<C>(&object, method_ptr);
}
template <class C>
static Delegate from(C const& object,
R (C::* const method_ptr)(A...) const)
{
return const_member_pair<C>(&object, method_ptr);
}
void reset() { stub_ptr_ = nullptr; store_.reset(); }
void reset_stub() noexcept { stub_ptr_ = nullptr; }
void swap(Delegate& other) noexcept { ::std::swap(*this, other); }
bool operator==(Delegate const& rhs) const noexcept
{
return (object_ptr_ == rhs.object_ptr_) && (stub_ptr_ == rhs.stub_ptr_);
}
bool operator!=(Delegate const& rhs) const noexcept
{
return !operator==(rhs);
}
bool operator<(Delegate const& rhs) const noexcept
{
return (object_ptr_ < rhs.object_ptr_) ||
((object_ptr_ == rhs.object_ptr_) && (stub_ptr_ < rhs.stub_ptr_));
}
bool operator==(::std::nullptr_t const) const noexcept
{
return !stub_ptr_;
}
bool operator!=(::std::nullptr_t const) const noexcept
{
return stub_ptr_;
}
explicit operator bool() const noexcept { return stub_ptr_; }
R operator()(A... args) const
{
// assert(stub_ptr);
return stub_ptr_(object_ptr_, ::std::forward<A>(args)...);
}
private:
friend struct ::std::hash<Delegate>;
using deleter_type = void (*)(void*);
void* object_ptr_;
stub_ptr_type stub_ptr_{};
deleter_type deleter_;
::std::shared_ptr<void> store_;
::std::size_t store_size_;
template <class T>
static void functor_deleter(void* const p)
{
static_cast<T*>(p)->~T();
operator delete(p);
}
template <class T>
static void deleter_stub(void* const p)
{
static_cast<T*>(p)->~T();
}
template <R (*function_ptr)(A...)>
static R function_stub(void* const, A&&... args)
{
return function_ptr(::std::forward<A>(args)...);
}
template <class C, R (C::*method_ptr)(A...)>
static R method_stub(void* const object_ptr, A&&... args)
{
return (static_cast<C*>(object_ptr)->*method_ptr)(
::std::forward<A>(args)...);
}
template <class C, R (C::*method_ptr)(A...) const>
static R const_method_stub(void* const object_ptr, A&&... args)
{
return (static_cast<C const*>(object_ptr)->*method_ptr)(
::std::forward<A>(args)...);
}
template <typename>
struct is_member_pair : std::false_type { };
template <class C>
struct is_member_pair< ::std::pair<C* const,
R (C::* const)(A...)> > : std::true_type
{
};
template <typename>
struct is_const_member_pair : std::false_type { };
template <class C>
struct is_const_member_pair< ::std::pair<C const* const,
R (C::* const)(A...) const> > : std::true_type
{
};
template <typename T>
static typename ::std::enable_if<
!(is_member_pair<T>{} ||
is_const_member_pair<T>{}),
R
>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (*static_cast<T*>(object_ptr))(::std::forward<A>(args)...);
}
template <typename T>
static typename ::std::enable_if<
is_member_pair<T>{} ||
is_const_member_pair<T>{},
R
>::type
functor_stub(void* const object_ptr, A&&... args)
{
return (static_cast<T*>(object_ptr)->first->*
static_cast<T*>(object_ptr)->second)(::std::forward<A>(args)...);
}
};
namespace std
{
template <typename R, typename ...A>
struct hash<::Delegate<R (A...)> >
{
size_t operator()(::Delegate<R (A...)> const& d) const noexcept
{
auto const seed(hash<void*>()(d.object_ptr_));
return hash<typename ::Delegate<R (A...)>::stub_ptr_type>()(
d.stub_ptr_) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
};
}
#endif // DELEGATE_HPP
As Igor commented, the following solves the problem: replace is_member_pair<T>{} with is_member_pair<T>::value everywhere and do the same for is_const_member_pair.

Can I initialize elements with an additional default-parameter using std::vector?

I'm currently working on my own little framework which has the following design pattern:
Each object inherits from LObject and has a parent which it informs when something has changed in the object.
Here's an example:
class LObject
{
public:
LObject(LObject* const _pParent = nullptr) :
_mpParent(_pParent),
_mChildrenCount(0)
{
if(parent() != nullptr)
_mChildId = parent()->GenerateChildId();
}
unsigned int id() const { return _mChildId; }
protected:
LObject* const parent() const { return _mpParent; }
unsigned int selfId() const { return -1; }
unsigned int GenerateChildId() const { return _mChildrenCount++; }
virtual void ChildChanged(unsigned int _childId)
{
if(parent() != nullptr)
parent()->ChildChanged(id());
}
virtual void ChildChanged() const
{
if(parent() != nullptr)
parent()->ChildChanged(id());
}
private:
LObject* const _mpParent;
unsigned int _mChildId;
mutable unsigned int _mChildrenCount;
};
template <typename T>
class LType : public LObject
{
public:
/// constructors
LType(LObject* const _pParent=nullptr) :
LObject(_pParent),
_mValue()
{}
LType(const T& _rcValue, LObject* const _pParent=nullptr) :
LObject(_pParent),
_mValue(_rcValue)
{}
/// template type
typedef T size_type;
/// modify data
void set(const T& _rcValue, bool _notifyParent=true)
{
_mValue = _rcValue;
if(_notifyParent)
ChildChanged();
}
void add(const T& _rcValue, bool _notifyParent=true); // same with +=
/// get data
const T& operator()() const; // returns _mValue
/// operators (modify / get data)
void operator=(const T& _rcValue); // same as set
private:
T _mValue;
};
class SomeObject : public LObject
{
public:
SomeObject(LObject* const _pParent = nullptr) :
LObject(_pParent),
someInt(this)
{}
LType<int> someInt;
virtual void ChildChanged(unsigned int _childId)
{
LObject::ChildChanged();
if(_childId == someInt.id())
std::cout << "someInt changed!" << std::endl;
}
};
int main(int argc, char* argv[])
{
SomeObject obj;
obj.someInt = 5;
return 0;
}
Output: someInt changed!
Now I want to implement a container class, which should work like this:
class SomeOtherObject : public LObject
{
public:
SomeOtherObject (LObject* const _pParent = nullptr) :
LObject(_pParent),
someContainer(this)
{}
LContainer<LType<int>> someContainer;
virtual void ChildChanged(unsigned int _childId)
{
LObject::ChildChanged();
if(_childId == someContainer.id())
std::cout << "someContainer changed!" << std::endl;
if(_childId == someContainer[0].id())
std::cout << "someContainer[0] changed!" << std::endl;
}
};
int main(int argc, char* argv[])
{
SomeOtherObject obj2;
obj.someContainer.push_back(5);
obj.someContainer[0].set(32);
return 0;
}
Depending on the implementation the output should be:
someContainer changed!
someContainer[0] changed!
or
someContainer changed!
someContainer changed!
(For the time being i don't care if the elements of the container are children of the container or if they have the same parent as the container.)
So as you see I want the container to work like std::vector, the only difference is, that objects that are created in there (with push_back or with insert) know their parent and that the container knows it's parent.
(Maybe I don't even care about the container knowing it's parent but I think it's mandatory)
In the best-case scenario I'd like to just use std::vector.
I didn't find any clues of a feature like a default value that's passed at the end of the std::vector::push_back parameter list in the cplusplus reference.
So my Questions:
Is a way and I just didn't find it?
if no, is there an easier way than completely reimplementing std::vector?
I want a container class for my little framework with as little implementations of allready existing methods from the STL as possible.
I'd like to implement it like that (if at all possible)
class LContainer : public std::vector, public LObject
{
LContainer(LObject* const _pParent) :
LObject(_pParent)
{
std::vector::addValuesWithDefaultParameter(parent()); // If something like that is available)
}
};
Edit: This is how i solved the problem.
I inherited from both LObject and std::vector and reimplemented the few functions that added something to the vector.
Notice: private inheritance is used to prevent users from typing obj.container.std::vector::push_back(element);
/// LContainer.h
template <typename T>
class LContainer : public LObject, std::vector<T>
{
public:
LContainer(LObject* const _pParent=nullptr);
LContainer(unsigned int _startSize, LObject* const _pParent=nullptr);
LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent=nullptr);
/// Iterators
using std::vector<T>::begin;
using std::vector<T>::end;
using std::vector<T>::rbegin;
using std::vector<T>::rend;
using std::vector<T>::cbegin;
using std::vector<T>::cend;
using std::vector<T>::crbegin;
using std::vector<T>::crend;
/// Capacity
using std::vector<T>::size;
using std::vector<T>::max_size;
void resize(unsigned int _newSize, const T& _rcValue);
using std::vector<T>::capacity;
using std::vector<T>::empty;
using std::vector<T>::reserve;
using std::vector<T>::shrink_to_fit;
/// Element access
using std::vector<T>::operator [];
using std::vector<T>::at;
using std::vector<T>::front;
using std::vector<T>::back;
/// add elements
void assign(unsigned int _count, const T& _rcValue);
void push_back(const T& _rcValue);
using std::vector<T>::pop_back;
void insert(unsigned int _position, const T& _rcValue);
void insert(unsigned int _position, unsigned int _count, const T& _rcValue);
using std::vector<T>::erase;
using std::vector<T>::swap;
using std::vector<T>::clear;
using std::vector<T>::emplace;
using std::vector<T>::emplace_back;
/// Allocator
using std::vector<T>::get_allocator;
private:
T _mElementDummy;
};
/// LContainer.inl file
template <typename T>
LContainer<T>::LContainer(LObject* const _pParent) :
LObject(_pParent),
std::vector<T>(),
_mElementDummy(_pParent)
{}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, LObject* const _pParent) :
LObject(_pParent),
std::vector<T>(),
_mElementDummy(_pParent)
{
while(std::vector::size() < _startSize)
std::vector::push_back(_mElementDummy);
}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent) :
LObject(_pParent),
std::vector<T>(),
_mElementDummy(_pParent)
{
_mElementDummy = _rcValue;
while(std::vector::size() < _startSize)
std::vector::push_back(_mElementDummy);
}
template <typename T>
void LContainer<T>::resize(unsigned int _newSize, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::resize(_mElementDummy, _mElementDummy);
}
template <typename T>
void LContainer<T>::assign(unsigned int _count, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::assign(_count, _mElementDummy);
}
template <typename T>
void LContainer<T>::push_back(const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::push_back(_mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::insert(_position, _mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, unsigned int _count, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::insert(_position, _count, _mElementDummy);
}
std::vector::push_back does not have the ability to take an additional parameter.
My suggestion:
Use composition instead of inheritance from std::vector to define LContainer.
class LContainer : public LObject
{
LContainer(LObject* const _pParent) : LObject(_pParent)
{
}
// Member variable
std::vector<LObject*> containedObjects_;
};
Add a function in LContainer to add objects. In this function, use std::vector::push_back and then do the necessary additional processing.
class LContainer : public LObject
{
LContainer(LObject* const _pParent) : LObject(_pParent)
{
}
void addObject(LObject* object)
{
containedObjects_.push_back(object);
// Do the additional processing.
// ...
//
}
// Member variable
std::vector<LObject*> containedObjects_;
};
The best solution I found was to inherit from both LObject and std::vector and reimplemented the few functions that added something to the vector.
Functionality from std::vector was taken with the keyword using.
Notice: private inheritance is used to prevent users from typing obj.container.std::vector::push_back(element);
/// LContainer.h
template <typename T>
class LContainer : public LObject, std::vector<T>
{
public:
LContainer(LObject* const _pParent=nullptr);
LContainer(unsigned int _startSize, LObject* const _pParent=nullptr);
LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent=nullptr);
/// Iterators
using std::vector<T>::begin;
using std::vector<T>::end;
using std::vector<T>::rbegin;
using std::vector<T>::rend;
using std::vector<T>::cbegin;
using std::vector<T>::cend;
using std::vector<T>::crbegin;
using std::vector<T>::crend;
/// Capacity
using std::vector<T>::size;
using std::vector<T>::max_size;
void resize(unsigned int _newSize, const T& _rcValue);
using std::vector<T>::capacity;
using std::vector<T>::empty;
using std::vector<T>::reserve;
using std::vector<T>::shrink_to_fit;
/// Element access
using std::vector<T>::operator [];
using std::vector<T>::at;
using std::vector<T>::front;
using std::vector<T>::back;
/// add elements
void assign(unsigned int _count, const T& _rcValue);
void push_back(const T& _rcValue);
using std::vector<T>::pop_back;
void insert(unsigned int _position, const T& _rcValue);
void insert(unsigned int _position, unsigned int _count, const T& _rcValue);
using std::vector<T>::erase;
using std::vector<T>::swap;
using std::vector<T>::clear;
using std::vector<T>::emplace;
using std::vector<T>::emplace_back;
/// Allocator
using std::vector<T>::get_allocator;
private:
T _mElementDummy;
};
/// LContainer.inl file
template <typename T>
LContainer<T>::LContainer(LObject* const _pParent) :
LObject(_pParent),
std::vector<T>(),
_mElementDummy(_pParent)
{}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, LObject* const _pParent) :
LObject(_pParent),
std::vector<T>(),
_mElementDummy(_pParent)
{
while(std::vector::size() < _startSize)
std::vector::push_back(_mElementDummy);
}
template <typename T>
LContainer<T>::LContainer(unsigned int _startSize, const T& _rcValue, LObject* const _pParent) :
LObject(_pParent),
std::vector<T>(),
_mElementDummy(_pParent)
{
_mElementDummy = _rcValue;
while(this->size() < _startSize)
std::vector::push_back(_mElementDummy);
}
template <typename T>
void LContainer<T>::resize(unsigned int _newSize, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::resize(_mElementDummy, _mElementDummy);
}
template <typename T>
void LContainer<T>::assign(unsigned int _count, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::assign(_count, _mElementDummy);
}
template <typename T>
void LContainer<T>::push_back(const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::push_back(_mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::insert(_position, _mElementDummy);
}
template <typename T>
void LContainer<T>::insert(unsigned int _position, unsigned int _count, const T& _rcValue)
{
_mElementDummy = _rcValue;
std::vector::insert(_position, _count, _mElementDummy);
}

BOOST_FOREACH without Boost?

Is there an implementation of a "for each" macro like BOOST_FOREACH that doesn't need Boost?
I've made one.
It should work with C++11 r-value references in GCC and MSVC, but I haven't tested it well so if there's any errors please let me know.
Edit: I added support for strings.
#include <iterator>
#include <utility>
#define foreach(v, r) \
if (fe_detail::any const &fe_r_ = \
fe_detail::make_range(r)) { } else \
if (fe_detail::any const &fe_b_ = \
fe_detail::begin(fe_r_, ((void)0, 1) ? NULL : fe_detail::twrap(r))) { } else \
if (fe_detail::equal( \
fe_b_, \
fe_detail::end(fe_r_, ((void)0, 1) ? NULL : fe_detail::twrap(r)), \
((void)0, 1) ? NULL : fe_detail::twrap(r))) { } else \
for (bool fe_c_ = false; \
!fe_c_ && !fe_detail::equal( \
fe_b_, \
fe_detail::end(fe_r_, ((void)0, 1) ? NULL : fe_detail::twrap(r)), \
((void)0, 1) ? NULL : fe_detail::twrap(r)); \
fe_detail::advance(fe_b_, 1, ((void)0, 1) ? NULL : fe_detail::twrap(r))) \
for (v = (fe_detail::move(*fe_detail::iter(fe_b_, ((void)0, 1) ? NULL : fe_detail::twrap(r)))); \
fe_c_ = !fe_c_; )
namespace fe_detail
{
// Container traits
template<class C, class It> struct CT
{
typedef It It;
static It begin(C &c) { return c.begin(); }
static It end(C &c) { return c.end(); }
};
// Range traits
template<class R> struct RT : public CT<R, typename R::iterator> { };
template<class R> struct RT<R const> : public CT<R const, typename R::const_iterator> { };
template<class R> struct RT<R &> : public RT<R> { };
template<class T, bool B = T::value> struct enable_if;
template<class T> struct enable_if<T, true> { typedef T type; };
template<class T> struct is_char { static bool const value = false; };
template<class T> struct is_char<T const> : public is_char<T> { };
template<class T> struct is_char<T volatile> : public is_char<T> { };
template<> struct is_char<char> { static bool const value = true; };
template<> struct is_char<wchar_t> { static bool const value = true; };
template<class Ch> struct RT<Ch *> : enable_if<is_char<Ch> >
{
typedef Ch *It;
static It begin(It a) { return &a[0]; }
static It end(It a) { return &a[std::char_traits<Ch>::length(a)]; }
};
template<class R, size_t N> struct RT<R[N]>
{
typedef R *It;
static It begin(It a) { return &a[0]; }
static It end(It a) { return &a[N - (((void)0, is_char<R>::value) ? 1 : 0)]; }
};
template<class It> struct RT<std::pair<It, It> >
{
typedef It It;
static It begin(std::pair<It, It> const a) { return a.first; }
static It end(std::pair<It, It> const a) { return a.second; }
};
struct any { operator bool() const { return false; } };
template<class T> struct type_wrap { type_wrap(bool = false) { } };
template<class T> class wrap : public any
{ wrap &operator =(wrap const &); public: mutable T v; wrap(T v) : any(), v(v) { } };
template<class T> class wrap<T const> : public any
{ wrap &operator =(wrap const &); public: T const v; wrap(T const v) : any(), v(v) { } };
template<class T, size_t N> class wrap<T[N]> : public any
{ wrap &operator =(wrap const &); public: T (&v)[N]; wrap(T (&v)[N]) : any(), v(v) { } };
template<class T> class wrap<T const &> : public wrap<T const>
{ wrap &operator =(wrap const &); public: wrap(T const &v) : wrap<T const>(v) { } };
template<class T, size_t N> wrap<T[N]> make_range(T (&r)[N]) { return r; }
template<class T, size_t N> type_wrap<T[N]> twrap(T (&r)[N]) { throw 0; }
template<class It> type_wrap<std::pair<It, It> > twrap(std::pair<It, It> const &p) { throw 0; }
#if defined(_MSC_VER) && _MSC_VER >= 1600 || defined(__RVALUE_REFERENCE) || defined(__GXX_EXPERIMENTAL_CXX0X__)
template<class R> struct RT<R &&> : public RT<R> { };
template<class T> class wrap<T &&> : public wrap<T> { public: wrap(T &&v) : wrap<T>(std::move(v)) { } };
template<class R> wrap<R &&> make_range(R &&r) { return wrap<R &&>(std::forward<R>(r)); }
template<class R> type_wrap<R> twrap(R &&) { throw 0; }
using std::move;
#else
template<class R> wrap<R> make_range(R &r) { return r; }
template<class R> wrap<R const &> make_range(R const &r) { return r; }
template<class R> type_wrap<R> twrap(R &) { throw 0; }
template<class R> type_wrap<R const &> twrap(R const &) { throw 0; }
template<class T> T &move(T &v) { return v; }
template<class T> T const &move(T const &v) { return v; }
#endif
template<class R> wrap<typename RT<R>::It> begin(any const &r, type_wrap<R>)
{ return RT<R>::begin(static_cast<wrap<R> const &>(r).v); }
template<class R> wrap<typename RT<R>::It> end(any const &r, type_wrap<R>)
{ return RT<R>::end (static_cast<wrap<R> const &>(r).v); }
template<class R> bool equal(any const &i, any const &j, type_wrap<R>)
{ return static_cast<wrap<typename RT<R>::It> const &>(i).v == static_cast<wrap<typename RT<R>::It> const &>(j).v; }
template<class R> void advance(any const &i, typename std::iterator_traits<typename RT<R>::It>::difference_type const d, type_wrap<R>)
{ return std::advance(static_cast<wrap<typename RT<R>::It> const &>(i).v, d); }
template<class R> typename RT<R>::It &iter(any const &i, type_wrap<R>)
{ return static_cast<wrap<typename RT<R>::It> const &>(i).v; }
}
You can use it like:
#include <vector>
#include <iostream>
std::vector<int> make_vect()
{
std::vector<int> v;
v.push_back(5);
v.push_back(8);
v.push_back(10);
return v;
}
int main()
{
foreach (int c, make_vect())
{
std::cout << c << std::endl;
}
}