#include <iostream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <tr1/memory>
#include <tr1/functional>
struct Data
{
int A, B, C;
};
class DataSpecification
{
public:
virtual bool IsSatisfiedBy(Data&) const = 0;
};
typedef std::tr1::shared_ptr<DataSpecification> DataSpecificationPtr;
class Validator
{
public:
void AddSpecification(DataSpecificationPtr spec)
{
specs_.push_back(spec);
}
bool IsValid(Data& data)
{
using std::tr1::placeholders::_1;
return specs_.end() != std::find_if(specs_.begin(), specs_.end(),
std::tr1::bind(&DataSpecification::IsSatisfiedBy, _1, data));
}
private:
std::vector<DataSpecificationPtr> specs_;
};
class DataLoader
{
public:
DataLoader(bool breakIfInvalid, const Validator& validator) :
validator_(validator),
breakIfInvalid_(breakIfInvalid),
a(0), b(1), c(2)
{
}
template<typename OutIter>
void Load(OutIter out)
{
while(HasNext())
{
Data data = LoadNext();
if (!validator_.IsValid(data))
{
if (breakIfInvalid_)
break;
else
continue;
}
out++ = data;
}
}
private:
bool HasNext()
{
return a < 10;
}
Data LoadNext()
{
Data d;
d.A = a++;
d.B = b++;
d.C = c++;
return d;
}
Validator validator_;
bool breakIfInvalid_;
int a, b, c;
};
class AGreaterMin : public DataSpecification
{
public:
AGreaterMin(int minA) : min_(minA){}
bool IsSatisfiedBy(Data& data) const
{
return data.A > min_;
}
int min_;
};
class BGreaterMin : public DataSpecification
{
public:
BGreaterMin(int minB) : min_(minB){}
bool IsSatisfiedBy(Data& data) const
{
return data.B > min_;
}
int min_;
};
template<typename DataContainer>
void PrintData(const DataContainer& c)
{
typedef typename DataContainer::const_iterator Iter;
for (Iter it = c.begin(), end = c.end(); it != end; ++it)
std::cout << it->A << " " << it->B << " " << it->C << "\n";
}
int main()
{
std::vector<Data> data;
Validator v;
v.AddSpecification(DataSpecificationPtr(new AGreaterMin(5)));
v.AddSpecification(DataSpecificationPtr(new BGreaterMin(7)));
DataLoader loader1(false, v);
loader1.Load(std::back_inserter(data));
PrintData(data);
data.clear();
std::cout << "Break if invalid:\n";
DataLoader loader2(true, v);
loader2.Load(std::back_inserter(data));
PrintData(data);
}
I2luY2x1ZGUgPGlvc3RyZWFtPgojaW5jbHVkZSA8aXRlcmF0b3I+CiNpbmNsdWRlIDxhbGdvcml0aG0+CiNpbmNsdWRlIDx2ZWN0b3I+CiNpbmNsdWRlIDx0cjEvbWVtb3J5PgojaW5jbHVkZSA8dHIxL2Z1bmN0aW9uYWw+CgoKc3RydWN0IERhdGEKewogICAgaW50IEEsIEIsIEM7Cn07CgoKY2xhc3MgRGF0YVNwZWNpZmljYXRpb24KewpwdWJsaWM6CiAgICB2aXJ0dWFsIGJvb2wgSXNTYXRpc2ZpZWRCeShEYXRhJikgY29uc3QgPSAwOwp9OwoKdHlwZWRlZiBzdGQ6OnRyMTo6c2hhcmVkX3B0cjxEYXRhU3BlY2lmaWNhdGlvbj4gRGF0YVNwZWNpZmljYXRpb25QdHI7CgoKY2xhc3MgVmFsaWRhdG9yCnsKcHVibGljOgogICAgdm9pZCBBZGRTcGVjaWZpY2F0aW9uKERhdGFTcGVjaWZpY2F0aW9uUHRyIHNwZWMpCiAgICB7CiAgICAgICAgc3BlY3NfLnB1c2hfYmFjayhzcGVjKTsKICAgIH0KCiAgICBib29sIElzVmFsaWQoRGF0YSYgZGF0YSkKICAgIHsKICAgICAgICB1c2luZyBzdGQ6OnRyMTo6cGxhY2Vob2xkZXJzOjpfMTsKICAgICAgICByZXR1cm4gc3BlY3NfLmVuZCgpICE9IHN0ZDo6ZmluZF9pZihzcGVjc18uYmVnaW4oKSwgc3BlY3NfLmVuZCgpLCAKICAgICAgICAgICAgc3RkOjp0cjE6OmJpbmQoJkRhdGFTcGVjaWZpY2F0aW9uOjpJc1NhdGlzZmllZEJ5LCBfMSwgZGF0YSkpOwogICAgfQpwcml2YXRlOgogICAgc3RkOjp2ZWN0b3I8RGF0YVNwZWNpZmljYXRpb25QdHI+IHNwZWNzXzsKfTsKCgpjbGFzcyBEYXRhTG9hZGVyCnsKcHVibGljOgogICAgRGF0YUxvYWRlcihib29sIGJyZWFrSWZJbnZhbGlkLCBjb25zdCBWYWxpZGF0b3ImIHZhbGlkYXRvcikgOgogICAgICAgIHZhbGlkYXRvcl8odmFsaWRhdG9yKSwKICAgICAgICBicmVha0lmSW52YWxpZF8oYnJlYWtJZkludmFsaWQpLCAKICAgICAgICBhKDApLCBiKDEpLCBjKDIpCiAgICB7CgogICAgfQoKICAgIHRlbXBsYXRlPHR5cGVuYW1lIE91dEl0ZXI+CiAgICB2b2lkIExvYWQoT3V0SXRlciBvdXQpCiAgICB7CiAgICAgICAgd2hpbGUoSGFzTmV4dCgpKQogICAgICAgIHsKICAgICAgICAgICAgRGF0YSBkYXRhID0gTG9hZE5leHQoKTsKICAgICAgICAgICAgaWYgKCF2YWxpZGF0b3JfLklzVmFsaWQoZGF0YSkpCiAgICAgICAgICAgIHsKICAgICAgICAgICAgICAgIGlmIChicmVha0lmSW52YWxpZF8pCiAgICAgICAgICAgICAgICAgICAgYnJlYWs7CiAgICAgICAgICAgICAgICBlbHNlCiAgICAgICAgICAgICAgICAgICAgY29udGludWU7CiAgICAgICAgICAgIH0KICAgICAgICAgICAgb3V0KysgPSBkYXRhOwogICAgICAgIH0KICAgIH0KCnByaXZhdGU6CgogICAgYm9vbCBIYXNOZXh0KCkKICAgIHsKICAgICAgICByZXR1cm4gYSA8IDEwOwogICAgfQoKICAgIERhdGEgTG9hZE5leHQoKQogICAgewogICAgICAgIERhdGEgZDsKICAgICAgICBkLkEgPSBhKys7CiAgICAgICAgZC5CID0gYisrOwogICAgICAgIGQuQyA9IGMrKzsKICAgICAgICByZXR1cm4gZDsKICAgIH0KCiAgICBWYWxpZGF0b3IgdmFsaWRhdG9yXzsKICAgIGJvb2wgYnJlYWtJZkludmFsaWRfOwogICAgaW50IGEsIGIsIGM7Cn07CgoKY2xhc3MgQUdyZWF0ZXJNaW4gOiBwdWJsaWMgRGF0YVNwZWNpZmljYXRpb24KewpwdWJsaWM6CiAgICBBR3JlYXRlck1pbihpbnQgbWluQSkgOiBtaW5fKG1pbkEpe30KCiAgICBib29sIElzU2F0aXNmaWVkQnkoRGF0YSYgZGF0YSkgY29uc3QKICAgIHsKICAgICAgICByZXR1cm4gZGF0YS5BID4gbWluXzsKICAgIH0KICAgIGludCBtaW5fOwp9OwoKY2xhc3MgQkdyZWF0ZXJNaW4gOiBwdWJsaWMgRGF0YVNwZWNpZmljYXRpb24KewpwdWJsaWM6CiAgICBCR3JlYXRlck1pbihpbnQgbWluQikgOiBtaW5fKG1pbkIpe30KCiAgICBib29sIElzU2F0aXNmaWVkQnkoRGF0YSYgZGF0YSkgY29uc3QKICAgIHsKICAgICAgICByZXR1cm4gZGF0YS5CID4gbWluXzsKICAgIH0KICAgIGludCBtaW5fOwp9OwoKCnRlbXBsYXRlPHR5cGVuYW1lIERhdGFDb250YWluZXI+CnZvaWQgUHJpbnREYXRhKGNvbnN0IERhdGFDb250YWluZXImIGMpCnsKICAgIHR5cGVkZWYgdHlwZW5hbWUgRGF0YUNvbnRhaW5lcjo6Y29uc3RfaXRlcmF0b3IgSXRlcjsKICAgIGZvciAoSXRlciBpdCA9IGMuYmVnaW4oKSwgZW5kID0gYy5lbmQoKTsgaXQgIT0gZW5kOyArK2l0KQogICAgICAgIHN0ZDo6Y291dCA8PCBpdC0+QSA8PCAiICIgPDwgaXQtPkIgPDwgIiAiICA8PCBpdC0+QyA8PCAiXG4iOwp9CmludCBtYWluKCkKewogICAgc3RkOjp2ZWN0b3I8RGF0YT4gZGF0YTsKICAgIFZhbGlkYXRvciB2OwogICAgdi5BZGRTcGVjaWZpY2F0aW9uKERhdGFTcGVjaWZpY2F0aW9uUHRyKG5ldyBBR3JlYXRlck1pbig1KSkpOwogICAgdi5BZGRTcGVjaWZpY2F0aW9uKERhdGFTcGVjaWZpY2F0aW9uUHRyKG5ldyBCR3JlYXRlck1pbig3KSkpOwoKCiAgICBEYXRhTG9hZGVyIGxvYWRlcjEoZmFsc2UsIHYpOwogICAgbG9hZGVyMS5Mb2FkKHN0ZDo6YmFja19pbnNlcnRlcihkYXRhKSk7CiAgICBQcmludERhdGEoZGF0YSk7CgogICAgZGF0YS5jbGVhcigpOwogICAgc3RkOjpjb3V0IDw8ICJCcmVhayBpZiBpbnZhbGlkOlxuIjsKICAgIERhdGFMb2FkZXIgbG9hZGVyMih0cnVlLCB2KTsKICAgIGxvYWRlcjIuTG9hZChzdGQ6OmJhY2tfaW5zZXJ0ZXIoZGF0YSkpOwogICAgUHJpbnREYXRhKGRhdGEpOwp9