Best extension mechanism to be able to adopt third-party dependencies?

  argument-dependent-lookup, c++

I am currently trying to get my feet wet with concepts. I tried to define a concept that could be implemented by users to adopt third-party data types for using them with my hypothetical library.

template <class T> concept Initable = requires (T&t) { { init(t) }; };
  // just for demonstration purposes, real concept makes more sense ...

Then, I tried to implement that concept for a type of a library that I do not control:

// namespace std {
  template <std::semiregular T>
  T& init(std::optional<T> &v) { /* contents not that important */ v = T{}; return *v; }
// }

Of course, I quickly found out that the concept is not implemented by std::optional<int>:

static_assert(Initable<std::optional<int>>, "Oh no!"); // Fails!

The reason, obviously, is two-phase lookup. init as an independent name, does not pick up my definition, because it is not available during phase-1. If I’d put the init definition above the definition of the Initable concept, it would work. If I’d put it into the std namespace, it would work too, since the name would be found via argument-dependent lookup during phase 2 look-up.

I would love to provide a way to implement that concept for third-party libraries without

  • relying on a particular include order,
  • populating third-party namespaces and
  • using too much boiler-plate code at the caller site.

What would be the best way for such an extension mechanism? Or is this against some fundamental principles?

Source: Windows Questions C++

LEAVE A COMMENT