yaml-cpp icon indicating copy to clipboard operation
yaml-cpp copied to clipboard

Implement a customization point for types not default constructible

Open ozars opened this issue 4 years ago • 0 comments
trafficstars

This patch adds a customization point YAML::decode_dispatcher<T>::dispatch which:

  • allows decoding types that aren't default constructible,
  • delegates to YAML::convert<T>::decode by default for backward compatibility,
  • is enabled only when compiled with C++17 or newer since it depends on std::optional.

Notes:

  • Compiling with C++17 automatically enables this feature.
  • Relevant tests are added. Tested it locally (gcc 10.2 on debian buster) to confirm all tests passes with both C++11 & C++17.
  • YAML_CPP_HAS_DECODE_DISPATCHER macro is exposed allowing checking this feature.
  • Its signature has an Enable template parameter giving more flexibility, e.g. to allow SFINAE downstream:
namespace YAML {
template <typename T, typename Enable = void>
struct decode_dispatcher {
  static std::optional<T> dispatch(const Node& node) {
   // ...
  }
};
}

Example:

#include <yaml-cpp/node/impl.h>

struct Vec3 {
  double x, y, z;
  Vec3(double x, double y, double z) : x(x), y(y), z(z) {}
  // ...
};

namespace YAML {
template<>
struct decode_dispatcher<Vec3> {
  static std::optional<Vec3> dispatch(const Node& node) {
    if(!node.IsSequence() || node.size() != 3)
      return std::nullopt;
    return Vec3(
      node[0].as<double>(),
      node[1].as<double>(),
      node[2].as<double>()
    );
  }
};
}

Possibly closes: #993.

ozars avatar Jul 15 '21 14:07 ozars