Code:
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
/**********************************************************************************************/
template
<
typename FContainer
, typename FIterator
, typename FMechanism
>
struct SSequenceWrapper
{
typedef FIterator iterator;
SSequenceWrapper
(
FContainer * fContainer
, FMechanism fMechanism
):
mContainer(fContainer)
, mMechanism(fMechanism)
{
}
FIterator begin()
{
return(FIterator(mContainer->begin(), mContainer->end(), mMechanism));
}
FIterator end()
{
return(FIterator(mContainer->end(), mContainer->end(), mMechanism));
}
FContainer * mContainer;
FMechanism mMechanism;
};
/**********************************************************************************************/
template
<
typename FIterator
, typename FMechanism
, typename FResult
>
struct SIteratorBase:
public std::iterator<std::input_iterator_tag, FResult>
{
SIteratorBase
(
FIterator fOrigin
, FIterator fTerminus
, FMechanism fMechanism
):
mOrigin(fOrigin)
, mTerminus(fTerminus)
, mMechanism(fMechanism)
{
}
FIterator mOrigin;
FIterator mTerminus;
FMechanism mMechanism;
};
template
<
typename FIterator
, typename FMechanism
, typename FResult
>
bool operator <
(
const SIteratorBase<FIterator, FMechanism, FResult> & fLHS
, const SIteratorBase<FIterator, FMechanism, FResult> & fRHS
)
{
return fLHS.mOrigin < fRHS.mOrigin;
}
template
<
typename FIterator
, typename FMechanism
, typename FResult
>
bool operator !=
(
const SIteratorBase<FIterator, FMechanism, FResult> & fLHS
, const SIteratorBase<FIterator, FMechanism, FResult> & fRHS
)
{
return fLHS.mOrigin != fRHS.mOrigin;
}
template
<
typename FIterator
, typename FMechanism
, typename FResult
>
size_t operator -
(
const SIteratorBase<FIterator, FMechanism, FResult> & fLHS
, const SIteratorBase<FIterator, FMechanism, FResult> & fRHS
)
{
return fLHS.mOrigin - fRHS.mOrigin;
}
/**********************************************************************************************/
template
<
typename FIterator
, typename FMechanism
, typename FTarget
>
struct SIteratorAccess:
public SIteratorBase<FIterator, FMechanism, FTarget>
{
SIteratorAccess
(
FIterator fOrigin
, FIterator fTerminus
, FMechanism fMechanism
):
SIteratorBase<FIterator, FMechanism, FTarget>(fOrigin, fTerminus, fMechanism)
{
}
FTarget operator * ()
{
return(this->mMechanism(*this->mOrigin));
}
SIteratorAccess & operator ++ ()
{
++this->mOrigin;
return(*this);
}
};
/**********************************************************************************************/
template
<
typename FIterator
, typename FMechanism
>
struct SIteratorSelect:
public SIteratorBase<FIterator, FMechanism, typename std::iterator<typename std::iterator_traits<FIterator>::iterator_category, typename std::iterator_traits<FIterator>::value_type>::value_type>
{
typedef std::iterator<typename std::iterator_traits<FIterator>::iterator_category, typename std::iterator_traits<FIterator>::value_type> iterator_traits;
typedef typename iterator_traits::value_type value_type;
SIteratorSelect
(
FIterator fOrigin
, FIterator fTerminus
, FMechanism fMechanism
):
SIteratorBase<FIterator, FMechanism, typename std::iterator<typename std::iterator_traits<FIterator>::iterator_category, typename std::iterator_traits<FIterator>::value_type>::value_type>(fOrigin, fTerminus, fMechanism)
{
while((fOrigin < fTerminus) && !fMechanism(*fOrigin))
{
++fOrigin;
}
this->mOrigin = fOrigin;
}
value_type operator * ()
{
return(*this->mOrigin);
}
SIteratorSelect & operator ++ ()
{
FIterator sOrigin(this->mOrigin);
FIterator sTerminus(this->mTerminus);
++sOrigin;
while((sOrigin < sTerminus) && !this->mMechanism(*sOrigin))
{
++sOrigin;
}
this->mOrigin = sOrigin;
return(*this);
}
};
/**********************************************************************************************/
template
<
typename FIterator
, typename FMechanism
>
struct SIteratorTransform:
public SIteratorBase<FIterator, FMechanism, typename std::iterator<typename std::iterator_traits<FIterator>::iterator_category, typename std::iterator_traits<FIterator>::value_type>::value_type>
{
typedef std::iterator<typename std::iterator_traits<FIterator>::iterator_category, typename std::iterator_traits<FIterator>::value_type> iterator_traits;
typedef typename iterator_traits::value_type value_type;
SIteratorTransform
(
FIterator fOrigin
, FIterator fTerminus
, FMechanism fMechanism
):
SIteratorBase<FIterator, FMechanism, typename std::iterator<typename std::iterator_traits<FIterator>::iterator_category, typename std::iterator_traits<FIterator>::value_type>::value_type>(fOrigin, fTerminus, fMechanism)
{
}
value_type operator * ()
{
return(this->mMechanism(*this->mOrigin));
}
SIteratorTransform & operator ++ ()
{
++this->mOrigin;
return(*this);
}
};
/**********************************************************************************************/
template
<
typename FTarget
, typename FContainer
, typename FMechanism
>
SSequenceWrapper<FContainer, SIteratorAccess<typename FContainer::iterator, FMechanism, FTarget>, FMechanism> Access
(
FContainer & fContainer
, FMechanism fMechanism
)
{
return(SSequenceWrapper<FContainer, SIteratorAccess<typename FContainer::iterator, FMechanism, FTarget>, FMechanism>(&fContainer, fMechanism));
}
template
<
typename FContainer
, typename FMechanism
>
SSequenceWrapper<FContainer, SIteratorSelect<typename FContainer::iterator, FMechanism>, FMechanism> Selector
(
FContainer & fContainer
, FMechanism fMechanism
)
{
return(SSequenceWrapper<FContainer, SIteratorSelect<typename FContainer::iterator, FMechanism>, FMechanism>(&fContainer, fMechanism));
}
template
<
typename FContainer
, typename FMechanism
>
SSequenceWrapper<FContainer, SIteratorTransform<typename FContainer::iterator, FMechanism>, FMechanism> Transformer
(
FContainer & fContainer
, FMechanism fMechanism
)
{
return(SSequenceWrapper<FContainer, SIteratorTransform<typename FContainer::iterator, FMechanism>, FMechanism>(&fContainer, fMechanism));
}
/**********************************************************************************************/
struct SSimple
{
SSimple
(
unsigned int fIdentifier
, const std::string & fName
):
mIdentifier(fIdentifier)
, mName(fName)
{
}
unsigned int mIdentifier;
std::string mName;
};
std::ostream & operator <<
(
std::ostream & fLHS
, const SSimple & fRHS
)
{
fLHS << "SSimple(" << fRHS.mIdentifier << ", \"" << fRHS.mName << "\");";
}
/**********************************************************************************************/
std::string AccessName
(
const SSimple & f
)
{
return(f.mName);
}
bool SelectOddIdentifier
(
const SSimple & f
)
{
return(f.mIdentifier % 2);
}
SSimple TransformName
(
const SSimple & f
)
{
return(SSimple(f.mIdentifier, '!' + f.mName));
}
/**********************************************************************************************/
template
<
typename FContainer
, typename FIterator
>
void Copy
(
FContainer & fContainer
, FIterator fDestination
)
{
copy(fContainer.begin(), fContainer.end(), fDestination);
}
int main
(
int argc
, char ** argv
)
{
using namespace std;
vector<SSimple> sSource;
sSource.push_back(SSimple(1, "Test1"));
sSource.push_back(SSimple(2, "Test2"));
sSource.push_back(SSimple(3, "Test3"));
sSource.push_back(SSimple(4, "Test4"));
sSource.push_back(SSimple(5, "Test5"));
/**********************************************************************************************/
/* These lines do not create a new collection. */
/**********************************************************************************************/
auto sSelected = Selector(sSource, SelectOddIdentifier);
auto sTransformed = Transformer(sSelected, TransformName);
auto sAccessed = Access<string>(sTransformed, AccessName);
/**********************************************************************************************/
/* These lines only decorate while the elements are being iterated over for sampling. */
/**********************************************************************************************/
Copy(sSource, ostream_iterator<SSimple>(cout, "\n"));
cout << '\n';
Copy(sSelected, ostream_iterator<SSimple>(cout, "\n"));
cout << '\n';
Copy(sTransformed, ostream_iterator<SSimple>(cout, "\n"));
cout << '\n';
Copy(sAccessed, ostream_iterator<string>(cout, "\n"));
}