C++ Logo

SG7

Advanced search

Subject: Re: Metaprogramming
From: David Rector (davrec_at_[hidden])
Date: 2020-10-26 15:08:26


> On Oct 26, 2020, at 2:51 PM, Ville Voutilainen <ville.voutilainen_at_[hidden]> wrote:
>
> On Mon, 26 Oct 2020 at 20:37, David Rector <davrec_at_[hidden]> wrote:
>> One alternative way to make meta content stand out: always express it via strings literals.
>>
>> I'm not trying to be cute: we could still do fragments semantically, while using string injection syntax, and thereby perhaps get the best of both worlds. E.g.:
>>
>> ```
>> consteval void create_var_42(const char *name) {
>> inject("int " + name + " = 42;");
>> }
>
> I don't see how that stands out. It seems to do quite the opposite,
> blend in in plain sight.
> Except for the need of all those +, which certainly stand out as noise.

I strongly agree with Jeremy, so there are now two objections to the syntax, and in particular its unfamiliarity.

Syntax is preciously easy to change and experiment with, relative to semantics.

Doesn't this committee (btw Jeremy I am not on the committee, have no power or influence), owe it to Andrew & Wyatt et al, given all the work they did on the semantics, to help them nail down a syntax that common users are comfortable with?

Let's take Andrew's book example. The goal is to factor out a metafunction that would ultimately produce this:

```
struct book {
private:
  std::string m_author;
public:
  std::string const& get_author() const {
    return m_author;
  }
  void set_author(std::string const& s) {
    m_author = s;
  }
  //...
};
```

Here is Andrew's proposed syntax:

```
template<typename T>
consteval meta::info property(string_view id) {
  string member_name = "m_" + id;
  string getter_name = "get_" + id;
  string setter_name = "set_" + id;
  return <class {
    private:
      T |# %{member_name} #|;
    public:
      T const& |# %{getter_name} #|() const {
        return |# %{member_name} #|;
      }
      void |# %{setter_name} #|(T const& x) {
        |# %{member_name} #| = x;
      }
  }>;
}

struct book {
  << property<string>("author");
  << property<string>("title");
  // other book properties
};
```

Here is one alternative, *which would use Andrew's very same semantics*, but simply changes the syntax to resemble an output stream users may be more familiar with. To me, this stands out at least as much, if not more (imagine all the string literals below are colored red in your IDE), yet remains familiar.

```

template<typename T>
consteval void inject_property(string_view id) {
  string member_name = "m_" + id;
  string getter_name = "get_" + id;
  string setter_name = "set_" + id;
  
  meta << "private:"
          " T " << member_name
       << "public: "
          "T const& " << getter_name << "() const {"
          " return " << member_name
       << "}"
          "void " << setter_name << "(T const& x) {"
       << member_name << " = x;"
          "}";
}

struct book {
  consteval {
    inject_property<string>("author");
    inject_property<string>("title");
    // other book properties
  }
};
```

Plenty of tweaks possible as well, all so easy to implement/try out.

The nice thing about enclosing meta content in quotes in this way is that initially, you can only allow certain "hygienic" formulations, giving errors wherever the user doesn't follow them -- but later on, you can ease the burdens, and permit string injection of full declarations and statements as I have shown it is possible to implement, should users identify specific examples that absolutely require it. It seems the perfect compromise.

I hope this committee will give this and other easy to implement syntactic alternatives serious consideration.

Dave



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

Older Archives on Google Groups