Date: Mon, 13 Jan 2020 20:39:55 -0700
Hi all,
if we have to add a new keyword (i.e. constpub) to make something like
this special case to work, I would suggest to add a keyword "property"
to allow special functions to be called using its name as variable for
assignment syntax.
//a.hpp
class A
{
public:
//read/write properties, have additional protection than using
"value" directly
property int v() { return value; } //read
property
property int v(int val) { value=val; return value; } //write
property, return type and param type don't need to match
property int v(short val) { value=val; return value; } //write
property, overload allowed, as long as it doesn't conflict with others
//read only property, no write property defined
property int& v_readonly() { return value_readonly; } //can
return reference to variable
//write only property, no read property defined
property void v_writeonly(int val) { value_writeonly=val; } //return
type can be void
//static read only property, static
property static int v_static() { return value_static; }
protected:
//protected property for use by inherited class
property int v_protected() { return value_protected; }
//read property
property void v_protected(const int& val) { value_protected=val; }
//write property, return type can be void
private:
int value;
int value_readonly;
int value_writeonly;
int value_protected;
static int value_static;
}
//main.cpp
#include "a.hpp"
int main()
{
int v=5;
A a{};
a.v=v+1; //ok
v=a.v; //ok
v=a.v_readonly; //ok
a.v_readonly=v; //error, not defined
a.v_writeonly=v; //ok;
v=a.v_writeonly; //error, not defined
v=a.v_static; //ok
a.v_static=v; //error, not defined
a.v_protected=v; //error, protected for inherited class
v=a.v_protected; //error, protected for inherited class
}
though it still use private variable, but property is more useful than
bare "constpub" variable.
Thanks,
Jianping
On 1/10/2020 08:46 PM, Jorg Brown via Std-Proposals wrote:
> On Thu, Nov 21, 2019 at 2:34 AM Andrew Tomazos via Std-Proposals
> <std-proposals_at_[hidden]
> <mailto: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
>
if we have to add a new keyword (i.e. constpub) to make something like
this special case to work, I would suggest to add a keyword "property"
to allow special functions to be called using its name as variable for
assignment syntax.
//a.hpp
class A
{
public:
//read/write properties, have additional protection than using
"value" directly
property int v() { return value; } //read
property
property int v(int val) { value=val; return value; } //write
property, return type and param type don't need to match
property int v(short val) { value=val; return value; } //write
property, overload allowed, as long as it doesn't conflict with others
//read only property, no write property defined
property int& v_readonly() { return value_readonly; } //can
return reference to variable
//write only property, no read property defined
property void v_writeonly(int val) { value_writeonly=val; } //return
type can be void
//static read only property, static
property static int v_static() { return value_static; }
protected:
//protected property for use by inherited class
property int v_protected() { return value_protected; }
//read property
property void v_protected(const int& val) { value_protected=val; }
//write property, return type can be void
private:
int value;
int value_readonly;
int value_writeonly;
int value_protected;
static int value_static;
}
//main.cpp
#include "a.hpp"
int main()
{
int v=5;
A a{};
a.v=v+1; //ok
v=a.v; //ok
v=a.v_readonly; //ok
a.v_readonly=v; //error, not defined
a.v_writeonly=v; //ok;
v=a.v_writeonly; //error, not defined
v=a.v_static; //ok
a.v_static=v; //error, not defined
a.v_protected=v; //error, protected for inherited class
v=a.v_protected; //error, protected for inherited class
}
though it still use private variable, but property is more useful than
bare "constpub" variable.
Thanks,
Jianping
On 1/10/2020 08:46 PM, Jorg Brown via Std-Proposals wrote:
> On Thu, Nov 21, 2019 at 2:34 AM Andrew Tomazos via Std-Proposals
> <std-proposals_at_[hidden]
> <mailto: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-13 21:42:29