fp extension for boost::optional
Consider a given interface:
namespace services
{
class IDataProvider
{
public:
using Data = std::string;
using Connection = boost::signals2::connection;
using FNewData = void(const Data&);
using FNewDataHandler = std::function<FNewData>;
virtual ~IDataProvider() = default;
virtual void start() = 0;
virtual void stop() = 0;
virtual void wait() = 0;
virtual Connection onNewData(const FNewDataHandler& handler) = 0;
};
} // end namespace service
Conditions:
The following code snippet implements described above.
namespace {
template<typename T>
boost::optional<const T&> toOp(const T& value)
{
return value;
}
template<typename T>
boost::optional<T&> toOp(T& value)
{
return value;
}
boost::optional<double> toDouble(const std::string& value)
{
try {
return boost::lexical_cast<double>(value);
}
catch (const boost::bad_lexical_cast& exc)
{
std::cerr << exc.what() << std::endl;
return boost::none;
}
}
} // end namespace
void DataConsumer::startDataHandler(service::IDataProvider& provider)
{
double acc = 0.0;
uint32_t errors = 0;
provider.onNewData([&acc, &errors, &provider](const services::IDataProvider::Data& data) mutable {
auto errorHandler = [&errors] () mutable {
std::cout << "a wrong data recieved" << std::endl;
errors += 1;
};
auto filter = [] (auto&& el)
{
return std::isgreaterequal(el, 0.0) && std::islessequal(el, 50.0);
};
auto log = [] (auto&& el) {
std::cout << "New Value accepted: " << el << std::endl;
};
/* In an old manner it would be look like this:
try {
auto value = boost::lexical_cast<double>(data);
print(value);
if (value >= 0 && value <= 50)
{
std::cout << "New Value accepted: " << value << std::endl;
acc += value;
}
}
catch (const boost::bad_lexical_cast& exc)
{
std::cerr << exc.what() << std::endl;
errors += 1;
};
*/
// it's an example of usage boost_optional_ext
acc += toOp(data)
| toDouble
| hof::match(print<double>, errorHandler)
| hof::filter_if(filter)
| hof::match_some(log)
<<= 0;
std::cout << "----step-----ACC-[" << acc << "] " << std::endl;
if (acc >= 100)
{
provider.stop();
}
});
provider.start();
provider.wait();
std::cout << "Final Acc: [" << acc << "], Errors: " << errors << std::endl;
}
run ./build.sh
The build artifacts are in ./Build/bin