Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement a customization point for types not default constructible #1010

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

ozars
Copy link

@ozars ozars commented Jul 15, 2021

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.

`YAML::decode_dispatcher<T>::dispatch` is used for decoding `YAML::Node`
to a type T when compiled with C++17 or newer. This is a backward
compatible change as the default library implementation calls
`YAML::convert<T>::decode`.

An example:

  ```cpp
  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>()
      );
    }
  };
  }
  ```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

custom converter for non default-constructable data-types
1 participant