C++ Logo


Advanced search

Subject: Re: P2320: "The Syntax of Static Reflection" feedback request
From: David Rector (davrec_at_[hidden])
Date: 2021-02-21 08:44:57

> On Feb 21, 2021, at 3:58 AM, Roland Bock via SG7 <sg7_at_[hidden]> wrote:
> On 19.02.21 15:34, David Rector wrote:
>> Here is another class of non-trivial examples to consider:
>> ```
>> template<class T, class U>
>> class Sum {
>> T t;
>> U u;
>> public:
>> Sum(T &t, U u) : t(t), u(u) {}
>> // Methods: the union of the methods of T and U.
>> // Wherever they "share" a method, such that names and
>> // signatures of method reflections m_t and m_u are the same
>> // (not necc. via inheritance) that method is implemented
>> // to return t.[:m:](…) + u.[:m:](…). Otherwise, it returns
>> // t.[:m:](…) or u.[:m:](…) individually.
>> // Conversion operators: construct from the relevant fields,
>> // but for any data T shares with U, need to add in the other’s
>> // data to the initializer.
>> explicit operator T();
>> explicit operator U();
>> };
> I understand the composition with forwarding functions. But what would be a real-world use case for `t.[:m:](…) + u.[:m:](…)`?
> Note that `operator+` might not be defined for the return type. Also, the signatures might differ in just the return type.

This could be precisely a mechanism which could be used for defining an arbitrary operator+ that works for all classes, via this kind of operator+ definition:

template <class T, class U>
class operator_plus_exists {…}; //sfinae detector

template<typename T, typename U,
         typename = std::enable_if_t<!operator_plus_exists <T, U>::value>>
Sum<T, U> operator+(T t, U u) {
  return Sum<T, U>(t, u);

Here’s how it might work, which remains elegant when the return types differ:

struct A {
  int f();
  int g();
  //data, ctor
struct B {
  int g();
  A h();
  //data, ctor
struct C {
  int f();
  int g();
  B h(); //NB different return type from B::h()!
  //data, ctor

int main() {
  A a1(…);
  A a2(…)
  B b(…)
  C c(…);

  auto res = a1 + a2 + b + c;

  res.f(); // = a1.f() + a2.f() + a3.f();
  res.g(); // = b.f();
  auto newres = res.h(); // = a1 + a2 + c

  newres.f(); // = a1.f() + a2.f() + c.f()

That was just off the top of my head and already looks like something with a heck of a lot of utility.

Andrew is right that metaprogramming is fundamentally different. I hope he and his team realize just how different it is, how many extraordinary possibilities are at our fingertips if they just give us properly general tools. Remember there is always that fallback option that would allow Sum<T,U> and any other metafunction to be written, albeit clumsily, but I also sincerely look forward to seeing what alternative Andrew & co can come up with, because I too would like to improve on that old alternative if it is possible.

But to be clear, the Sum<T, U> example, and others of that level of complexity, *definitely need to be supported*. If Andrew et al disagree, I think we deserve an explicit statement to that effect. There is a lot of functionality at stake here.

SG7 list run by sg7-owner@lists.isocpp.org

Older Archives on Google Groups