C++ Logo

std-proposals

Advanced search

Re: Proposal of constpub (DRAFT 1)

From: Jorg Brown <jorg.brown_at_[hidden]>
Date: Fri, 10 Jan 2020 19:46:34 -0800
On Thu, Nov 21, 2019 at 2:34 AM Andrew Tomazos via Std-Proposals <
std-proposals_at_[hidden]> wrote:

> Please find attached a 2-page draft proposal entitled:
>
> Proposal of constpub
>
> It seems a little thing but easy to implement and I think it may have
> broad appeal.
>
> Anyway, initial thoughts appreciated.
> -Andrew.
>

Interesting...

>From the paper:

For example:


> struct S {

  constpub int i;

  void f() {

    std::cout << i; // OK: private read

    i = 42; // OK: private write

  }

};


> int main() {

  S s;

  std::cout << s.i; // OK: public read

  s.i = 42; // ERROR: public write

}


> This is an extremely common thing to want to do.


You've stated correctly in the paper that the common way to handle this is
to provide a public read-only accessor function.

There's another way to handle it, though: you could use a constexpr
reference:

struct S {
  constexpr const int& i = private_i;
  void f() {
    std::cout << private_i << '\n'; // OK: private read
    private_i = 42; // OK: private write
  }

 private:
  int private_i;
};

int main() {
  S s{};
  s.f();
  std::cout << s.i << '\n'; // OK: public read
  s.i = 42; // ERROR: public write
  s.private_i = 42; // ERROR: public access to private var
}

Obligatory godbolt reference: https://godbolt.org/z/7ieE4h

Now, there's three problems with this:

1) The standard does not allow non-static data members to be declared
constexpr.
2) If you remove the constexpr, this all works but the reference now
consumes memory in the struct.
3) If the struct is copied, the reference is also copied, and so the
reference now refers to the original struct.

But (1) Isn't just bad news: it's also good news. It means that in a
future C++, we could allow programmers to declare a constexpr member that
was a reference, that satisfied our needs: always referring to what it said
it referred to, no matter if a copy happened or not, and it would be
backwards-compatible with existing code.

It doesn't 100% satisfy what you're looking for, since the private member
and the public member would have different names, but I assume that would
be OK with you.

Regarding "this is an extremely common thing to want to do", that's
absolutely true for me, because we often want to migrating existing code.
For example, we might want an associative container whose elements have two
members: "key" and "value". But for compatibility, we might also want to
refer to them as "first" and "second".

And on a related note, while I might want my container code to be able to
access "key' and "value" in a mutable way, I might want my users to have
read/write access to "value", but be limited to read-only access to "key".

-- Jorg

Received on 2020-01-10 21:49:18