项目作者: vgordievskiy

项目描述 :
fp extension for boost::optional
高级语言: C++
项目地址: git://github.com/vgordievskiy/boost_optional_ext.git
创建时间: 2020-10-11T22:14:54Z
项目社区:https://github.com/vgordievskiy/boost_optional_ext

开源协议:MIT License

下载


boost_optional_ext

It is a pipe operator for the boost::optional

it gives you a way to write your code in an FP manner.

Sample

Consider a given interface:

  1. namespace services
  2. {
  3. class IDataProvider
  4. {
  5. public:
  6. using Data = std::string;
  7. using Connection = boost::signals2::connection;
  8. using FNewData = void(const Data&);
  9. using FNewDataHandler = std::function<FNewData>;
  10. virtual ~IDataProvider() = default;
  11. virtual void start() = 0;
  12. virtual void stop() = 0;
  13. virtual void wait() = 0;
  14. virtual Connection onNewData(const FNewDataHandler& handler) = 0;
  15. };
  16. } // end namespace service

Conditions:

  • a new data comes as the std::string
  • a new data is a textual representation of floating-point type with the sign.
  • the data may have an error (it isn’t a correct representation of floating-point type)
  • it’s required to sum all numbers are satisfying criterion: num > 0 and num < 50
  • it’s required to sum a count of errors.
  • The criterion of stop: the sum >= 100.

The following code snippet implements described above.

  1. namespace {
  2. template<typename T>
  3. boost::optional<const T&> toOp(const T& value)
  4. {
  5. return value;
  6. }
  7. template<typename T>
  8. boost::optional<T&> toOp(T& value)
  9. {
  10. return value;
  11. }
  12. boost::optional<double> toDouble(const std::string& value)
  13. {
  14. try {
  15. return boost::lexical_cast<double>(value);
  16. }
  17. catch (const boost::bad_lexical_cast& exc)
  18. {
  19. std::cerr << exc.what() << std::endl;
  20. return boost::none;
  21. }
  22. }
  23. } // end namespace
  24. void DataConsumer::startDataHandler(service::IDataProvider& provider)
  25. {
  26. double acc = 0.0;
  27. uint32_t errors = 0;
  28. provider.onNewData([&acc, &errors, &provider](const services::IDataProvider::Data& data) mutable {
  29. auto errorHandler = [&errors] () mutable {
  30. std::cout << "a wrong data recieved" << std::endl;
  31. errors += 1;
  32. };
  33. auto filter = [] (auto&& el)
  34. {
  35. return std::isgreaterequal(el, 0.0) && std::islessequal(el, 50.0);
  36. };
  37. auto log = [] (auto&& el) {
  38. std::cout << "New Value accepted: " << el << std::endl;
  39. };
  40. /* In an old manner it would be look like this:
  41. try {
  42. auto value = boost::lexical_cast<double>(data);
  43. print(value);
  44. if (value >= 0 && value <= 50)
  45. {
  46. std::cout << "New Value accepted: " << value << std::endl;
  47. acc += value;
  48. }
  49. }
  50. catch (const boost::bad_lexical_cast& exc)
  51. {
  52. std::cerr << exc.what() << std::endl;
  53. errors += 1;
  54. };
  55. */
  56. // it's an example of usage boost_optional_ext
  57. acc += toOp(data)
  58. | toDouble
  59. | hof::match(print<double>, errorHandler)
  60. | hof::filter_if(filter)
  61. | hof::match_some(log)
  62. <<= 0;
  63. std::cout << "----step-----ACC-[" << acc << "] " << std::endl;
  64. if (acc >= 100)
  65. {
  66. provider.stop();
  67. }
  68. });
  69. provider.start();
  70. provider.wait();
  71. std::cout << "Final Acc: [" << acc << "], Errors: " << errors << std::endl;
  72. }

How to configure and build example and tests

  1. run ./configure.sh
  2. run ./build.sh

    The build artifacts are in ./Build/bin