class Test
{
int _number;
std::pair<int, int> _twoNumbers;
public:
// getter
int number() auto {
return _number;
}
// setter
int number(int number) auto {
return _number = number;
}
// getter by reference
const pair<int, int> &twoNumbers() const auto {
return _twoNumbers;
}
// setter
const pair<int, int> &twoNumbers(const pair<int, int> &tn) auto {
return (_twoNumbers = tn);
}
};
/////////////////////////
Test test;
test.number = 5;
//same as: test.number(5);
int a = test.number;
// same as: int a = test.number();
test.number += 5;
// same as: test.number( test.number() + 5 );
int a = 1 + test.number + 3;
// same as: int a = 1 + test.number() + 3;
cout << number.twoNumbers.first << endl;
// same as: cout << number.twoNumbers().first << endl;
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
The case for properties has already been made. Java, C#, C++/CLI, Objective-C, and D all benefit from properties, and if C++ were to include them, a great many people would happily adopt them into their coding style. The amount of questions and library-based solutions you can find on Google should be more than enough to make that point.
How about doing the change in the other end:
Don't change anything in the class head, but allow an implicit transformation:
object.property = value;
to
object.property(value);
IFF property is a function which has an overload that can be called with a single parameter of value's type.
As function pointers and functions are different I don't see that this can interfer with an assignment that is allowed today. Also this is consistent with what is already allowed at construction time!
The getter case is a little harder to accept for me, but I think it would be possible to allow:
int value = object.property;
IFF property is a method which has a 0-ary overload.
I am not positive but at least I think that using the address of a method without a leading & is not allowed when you really want to get at the method pointer, so this should not be ambiguous. In contrast, it would not be possible to omit the trailing () for a global function as (due to feature inheritance from C) this means the address of the function (correct me if I'm wrong on this).
class TimePeriod { private double seconds; public double Hours { get { return seconds / 3600; } set { seconds = value * 3600; } } }The only advantage would be that you only have to mention the name Hours once. Instead you get an extra brace level and the keywords get and set. To me that's about even, and I think the C++ class head would look much cleaner:
--
---
You received this message because you are subscribed to the Google Groups "ISO C++ Standard - Future Proposals" group.
To unsubscribe from this group and stop receiving emails from it, send an email to std-proposal...@isocpp.org.
To post to this group, send email to std-pr...@isocpp.org.
Visit this group at http://groups.google.com/a/isocpp.org/group/std-proposals/.
-- Bengt Gustafsson CEO, Beamways AB Westmansgatan 37A 582 16 Linköping, Sweden
Do they really have syntax which is significiantly simpler than the classic setter/getter pair of C++?
Do they really have syntax which is significiantly simpler than the classic setter/getter pair of C++?
Here is Microsoft's example for C#:
class TimePeriod { private double seconds; public double Hours { get { return seconds / 3600; } set { seconds = value * 3600; } } }
There still has been zero cases made for why anyone thinks C++ needs
these besides "C# does it" or the like. What problems do properties
solve that are unsolved (or poorly/awkwardly solved) right now in
C++11/14? It's not satisfying my worries that are important (I have
zero say on what goes into the standard), but the committee is going
to ask these questions, demand answers, and are usually
_significantly_ more conservative than I am being here. :)
I have to disagree with this.
With Richard's implementation, taking sizeof(property<int>) yields 48 bytes.
The function pointers can be done away with using some very convoluted template syntax, but the reference to the container must still exist, making the minimum possible size of a library based property 4 bytes, which is still not negligible.
I have to disagree with this.
With Richard's implementation, taking sizeof(property<int>) yields 48 bytes.So if you had an object with 10 properties, you would have a half a kilobyte of extra data per instance.The function pointers can be done away with using some very convoluted template syntax, but the reference to the container must still exist, making the minimum possible size of a library based property 4 bytes, which is still not negligible.
On Wednesday, 28 August 2013 15:13:26 UTC-4, Magnus Fromreide wrote:
On Wed, 2013-08-28 at 20:17 +0300, Ville Voutilainen wrote:
>
>
>> On 28 August 2013 20:00, Sean Middleditch <se...@middleditch.us> wrote:
> There is one thing I am going to ask before anything else:
>
> What on earth do we need besides a library solution pretty much like
> what
>
> Richard outlined, and why would we need anything other than that?
>
One thing an explicit property buys over library solutions is that the
reference to the containing instance becomes implicit.
No, I do not think that is enough of an advantage to add properties to
the language.
/MF
On Wed, Aug 28, 2013 at 12:52 PM, Nick <nicolas.j...@gmail.com> wrote:I have to disagree with this.
With Richard's implementation, taking sizeof(property<int>) yields 48 bytes.So if you had an object with 10 properties, you would have a half a kilobyte of extra data per instance.The function pointers can be done away with using some very convoluted template syntax, but the reference to the container must still exist, making the minimum possible size of a library based property 4 bytes, which is still not negligible.Yes, the code I presented is not ideal, in a number of ways. The storage overhead is one. Another is that "a.number = b.number" does not compile, and classes containing such properties become non-copyable ("a.number = b.number;" would need to do different things depending on whether it happens in the surrounding class's copy-assignment operator).But... if we can find a set of language changes that suffice to make a library implementation of properties work better, we are likely to improve the language as a whole rather than adding a single point feature.
template<typename T, class C, T(C::*get)(), void(C::*set)(T)>
struct property {
C *object;
property(C *object) : object(object){}
operator T() { return (object->*get)(); }
template<typename U> property &operator=(U &&u) { (object->*set)(std::forward<U>(u)); return *this; }
}
struct Point
{
float x, y;
Point(float x = 0, float y = 0) : x(x), y(y){}
};
struct Test {
property<Point, ...> point;
};
Test test;
cout << test.point.x << endl;
const T* property::operator->() { return &(object->*get)(); }
Point& operator+=(const Point &p) { x += p.x; y += p.y; return *this; }
test.point += Point(5, 6);
template<typename U>
property &operator+=(U &&u) {
T tmp = (object->*get)();
tmp += u;
(object->*set)(std::forward<U>(tmp));
return *this;
}
property<int> number = {
[&]() { return _number; },
[&](int number) { _number = number; }
};
decltype(test.number);
auto num = test.number;
std::find(..., test.number);
//etc
Le 28/08/2013 15:42, Ville Voutilainen a �crit :
Lo�c
could you clarify what you mean by non-auto property?
vector<T> {
size_t size() const { return _last - _first; }
};
vector<int> myVec;
size_t sz = myVec.size();
vector<T> {
auto_property size_t size() const { return _last - _first; }
};
vector<int> myVec;
size_t sz1 = myVec.size();
size_t sz2 = myVec.size;
If properties are syntactically a good and wanted thing, then they deserve the dignity of being a proper language feature. And if
On 29 August 2013 04:42, Nick <nicolas.j...@gmail.com> wrote:
On Wednesday, 28 August 2013 20:59:49 UTC-4, Ville Voutilainen wrote:On 29 August 2013 02:04, Nicol Bolas <jmck...@gmail.com> wrote:
If properties are syntactically a good and wanted thing, then they deserve the dignity of being a proper language feature. And if
Do people think properties should be a language feature, when they are seemingly just one of the many
things compile-time reflection can provide?I keep hearing people try to relate reflection to properties. This doesn't make any sense to me at all. Can you provide a pseudo code example of how a property would be retrieved using a reflection interface?Depends on how far people are willing to go with reflection. ;) One of the expectations of people proposing
reflection facilities is that1) you can query the member functions and member data of a type
2) you can customize how a type answers to such queries
The part 2 may effectively involve being able to more or less overload operator. or its equivalent
so that when queried for a member f() or x, the type can return whatever it pleases, a reference to an existing member
of the type itself, a reference to a subobject or a member thereof, or something more dynamic.Completely imaginary, with quite a bunch of potentially controversial facilities:struct X
{private:int y;public:template<compile_time_string s> decltype(auto) operator-><s>()
{static if (s == "x") {
return y;} else {static_assert(false, "no such member");}}};
The use is thenX x;
int foo = x.x;or more verbosely,X x;int foo = std::reflection::member<compiletimestring("x")>(x);
Do people think properties should be a language feature, when they are seemingly just one of the many
things compile-time reflection can provide?I keep hearing people try to relate reflection to properties. This doesn't make any sense to me at all. Can you provide a pseudo code example of how a property would be retrieved using a reflection interface?Depends on how far people are willing to go with reflection. ;) One of the expectations of people proposing
reflection facilities is that1) you can query the member functions and member data of a type
2) you can customize how a type answers to such queries
But there's no coherent proposal for reflection that includes these things as of yet. Not unless I missed a paper somewhere. It
seems silly to dismiss a proposal because of something that might happen in the future.
template<compile_time_string s> decltype(auto) operator-><s>()
{static if (s == "x") {
return y;} else {static_assert(false, "no such member");}}};
The use is thenX x;
int foo = x.x;or more verbosely,X x;int foo = std::reflection::member<compiletimestring("x")>(x);
OK, where's the part that lets you do `x.x = 4`? Or `x.x = k`, where k is a type that is *not* implicitly convertible to x.x's type? Or the
part that lets you have multiple properties with different types (say, an int and a float)? Or the part that makes this increasing mass
Why are people so willing to settle for this kind of hackery? Have we learned nothing from the `enable_if` horrors? If this is an
important feature, it needs to be done right. And if it's not, it shouldn't be done at all. We should focus on settling whether it's important enough to go into the standard; if it is, it needs to be a language feature.
Has anyone considered using "auto" as a qualifier to specify that a function is a property?
On 29 August 2013 09:54, Nicol Bolas <jmck...@gmail.com> wrote:
Do people think properties should be a language feature, when they are seemingly just one of the many
things compile-time reflection can provide?I keep hearing people try to relate reflection to properties. This doesn't make any sense to me at all. Can you provide a pseudo code example of how a property would be retrieved using a reflection interface?Depends on how far people are willing to go with reflection. ;) One of the expectations of people proposing
reflection facilities is that1) you can query the member functions and member data of a type
2) you can customize how a type answers to such queries
But there's no coherent proposal for reflection that includes these things as of yet. Not unless I missed a paper somewhere. ItCorrect. The reflection study group hasn't even properly kicked to gear yet.
seems silly to dismiss a proposal because of something that might happen in the future.Well, there has been no such dismissal, so I don't see what you're complaining about.
template<compile_time_string s> decltype(auto) operator-><s>()
{static if (s == "x") {
return y;} else {static_assert(false, "no such member");}}};
The use is thenX x;
int foo = x.x;or more verbosely,X x;int foo = std::reflection::member<compiletimestring("x")>(x);
OK, where's the part that lets you do `x.x = 4`? Or `x.x = k`, where k is a type that is *not* implicitly convertible to x.x's type? Or theIn the part where I return a reference to y.
part that lets you have multiple properties with different types (say, an int and a float)? Or the part that makes this increasing massThere's no restriction against having multiple properties with different types in that pseudocode.
Why are people so willing to settle for this kind of hackery? Have we learned nothing from the `enable_if` horrors? If this is anBecause sometimes people are willing to strive for a general facility that may not be optimal for one of the cases
it covers, like properties, when the general facility provides much more than just a single feature.
seems silly to dismiss a proposal because of something that might happen in the future.Well, there has been no such dismissal, so I don't see what you're complaining about.
*ahem*: "Do people think properties should be a language feature, when they are seemingly just one of the manyThat sounds dismissive. Since you're dismissing properties as "one of the many things compile-time reflection can provide". That sounds very much like, "wait for reflection". Which is dismissive.
things compile-time reflection can provide?"
Or, let me put it this way:
There is no way to make properties as a hack, either via some library type or via reflection, and still have it fulfill all of these requirements, such that making a property:
1: Is easy for new C++ users to learn to use.
2: Is easy for new C++ users to read in other people's code.
3: Is reasonably compact in syntax.
4: Doesn't change the nature of the type on which it is placed.
5: Doesn't break the abstraction.
6: Has all of the features of properties in other languages that are appropriate to C++.
You may be able to make it function with reflection. But it won't ever be a good feature that people will want to use and teach others to use. With reflection, it'll merely be a curiosity that maybe some advanced C++ programmers will provide.
template<compile_time_string s> decltype(auto) operator-><s>()
{static if (s == "x") {
return y;} else {static_assert(false, "no such member");}}};
The use is thenX x;
int foo = x.x;or more verbosely,X x;int foo = std::reflection::member<compiletimestring("x")>(x);
OK, where's the part that lets you do `x.x = 4`? Or `x.x = k`, where k is a type that is *not* implicitly convertible to x.x's type? Or theIn the part where I return a reference to y.
Except that the reference to `y` returns a `Type&` (where `Type` is `y`'s type). And as I stated, if `k` is not implicitly convertible to `Type`, then doing `x.x = k` will not work. The actual properties feature would allow the user to specify multiple `set` methods, each of which could take any type.
Also, what of the possibility where there is no actual `y` at all? That's a very common use of properties: to create getters/setters for a "variable" that doesn't exist. Or that you don't want to expose `Type&`? Do you have to create some proxy type to do the actual getting/setting? Because that's not sounding like a good feature anymore.
part that lets you have multiple properties with different types (say, an int and a float)? Or the part that makes this increasing massThere's no restriction against having multiple properties with different types in that pseudocode.
I can't imagine how that could possibly work, since your `operator-><s>` can only return a single type. Not unless "multiple properties" means "multiple properties that all happen to use the same type". And you can't declare two of these `operator-><s>` things unless they take different parameters. Which they don't.
Not unless you mean to use a concept or something to conditionally activate or deactivate different instantiations based on `<s>`. Because that's not helping the case for this being a good idea; that just makes the complex feature even moreso.
Why are people so willing to settle for this kind of hackery? Have we learned nothing from the `enable_if` horrors? If this is anBecause sometimes people are willing to strive for a general facility that may not be optimal for one of the cases
it covers, like properties, when the general facility provides much more than just a single feature.
So what if they are? That doesn't explain why a hack is better than a real feature. Or should we abandon concepts since `enable_if` and such hackery can get us there anyway?
That presupposes the idea that if we had such reflection, we necessarily shouldn't have real properties, because you could get maybe most of properties working in a much less easily understood, hacky, and less readable way. That no IDE would ever be able to understand without having a full-fledged compiler built into it.
That the general facility might allow 80% of some idea to be implemented doesn't mean that the 20% it doesn't work for stops being important. Or that the pain of using the facility in that way should be ignored.
I'm not saying that we shouldn't have reflection. I'm saying that reflection is no substitute for properties if that's a feature we want.
import std.stdio;
struct Foo{ @property int data() { return m_data; } @property int data(int value) { writeln("set int"); return m_data = value; } @property int data(float value) { writeln("set float"); return m_data = cast(int)value; } private: int m_data;}
void main(){ Foo foo; foo.data = 1; foo.data = 2.0f; writef("Result %s\n", foo.data);}
"Oh. I must admit I'm unaware of an existing property system that allows multiple setters."
The D language property system(which I made reference to in my first post) does:
import std.stdio;struct Foo{@property int data() {return m_data;}@property int data(int value) {writeln("set int");return m_data = value;}@property int data(float value) {writeln("set float");return m_data = cast(int)value;}private: int m_data;}void main(){Foo foo;foo.data = 1;foo.data = 2.0f;writef("Result %s\n", foo.data);}output:set intset float2
As far as this function goes, which I agree is quite imaginary, I don't see how it would provide a better, if any, solution to the problems that properties solve."template<compile_time_string s> decltype(auto) operator-><s>()"
Object *object;
Class->GetType()->GetMethod("Foo")->Invoke(object);
Object *object;
Class->GetType()->GetField("number")->SetInt(object, 5);
object->set(5);
and in terms of anything happening at compile time, that pretty much falls under the category of a library implementation, which IMO has been thoroughly discussed already, and ruled out as far as standardization goes.
I mean no disrespect here, but it's starting to seem a little like you haven't even read half the posts in this thread.
"What we have is vocal opinions from people who aren't trying to explore the library possibilities"I am really lost as to how you can claim that the idea of a library implementation of properties hasn't been explored. A rather naive search on Google will easily produce at least 3-4 attempted implementations within the first couple of pages.
On 29 August 2013 19:26, Nick <nicolas.j...@gmail.com> wrote:
and in terms of anything happening at compile time, that pretty much falls under the category of a library implementation, which IMO has been thoroughly discussed already, and ruled out as far as standardization goes.I have seen zero evidence of any "ruling out". What we have is vocal opinions from people
who aren't trying to explore the library possibilities, or any other possibilities for that matter,
very hard.
auto data = variableName.field;
variableName.field = data2;
auto data = variableName.SomeGetterFunction();
variableName.SomeSetterFunction(data2);
class vec3
{
public:
float GetX() {return _x;}
float GetY() {return _y;}
float GetZ() {return _z;}
void SetX(float val) {_x = val;}
void SetY(float val) {_y = val;}
void SetZ(float val) {_z = val;}
private:
float _x, _y, _z;
};
vec3 vec(...);
vec.x = 4;
auto data = vec.z;
If someone wants to propose properties, such alternatives need to be explored
by a proposal paper, otherwise I see little reason to say anything but "thanks for sharing"
about such a proposal.
* Since `field` is a non-static data member, it takes up space. Even if it's just one `char` in size, it has already broken the layout of your class. You therefore cannot use these properties on any class that has strict layout needs. Let alone strict memory needs.
If someone wants to propose properties, such alternatives need to be explored
by a proposal paper, otherwise I see little reason to say anything but "thanks for sharing"
about such a proposal.
Why?
It's a simple question. Why?
No other proposals had to go through that. I don't recall Bjarne Stroustrup having to explore Boost.ConceptCheck before talking
about innumerable versions of concepts. I don't recall the people proposaing static_if having to explore various Macro methods and such before making their proposal. I don't recall the r-value reference guys having to try to implement Boost.Move before
being able to get people to look seriously at in-language move support. Are you saying that the the reflection group should have to investigate all possible library solutions for compile-time reflection before talking about their wanted language features?
And if they could do that, then why is required that properties proponents explore alternative "solutions" in order for them to get a reasonable hearing on the idea of a language feature? What is so special about properties as a construct that it needs to have someone explore all of the myriad of ways that it cannot possibly work as a library feature?
I think the reason you want this "exploration" of library implementations is that you don't want properties. Ever. What you want is to
No other C++ feature was built this way. I didn't see uniform initialization doing that. They didn't have to go through Boost.Assign and build up a random list of features that would make Boost.Assign work more cleanly. They came up with a completely separate syntax. They said that they could do it better and more reasonably by ignoring the library kludge and doing it right.
I didn't see lambdas proposal going through Boost.Lambda and Boost.Phoenix, picking and choosing places where they could maybe add a few low-impact language features that would improve various aspects of the implementation and some such. No, they ignored the library kludge and did it right.
One simple real-world example:
let's say there is an internal mutable mutex and the count have to lock it in the new version of the code to add thread safety (in a poor but correct way).
From:struct K
{
int count;
};
To:
struct K
{
// ... additional thread-safe manipulation functions
int count() const { std::lock_guard<std::mutex> _(m_mutex); return m_count; }
private:
mutable std::mutex m_mutex;
int m_count;
};
That's the kind of change that happen regularly in big code bases, in particular when thread-safety becomes important.
On Fri, Aug 30, 2013 at 4:33 PM, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:Let me get this out of the way first. Even though people tell me I
> Second, no, that's not stupid (please stay polite),
have a high level of fluency in English, it isn't my native language
so I apologise if I inadvertently crossed a line somewhere.
When I think an idea is stupid, I say that the idea is stupid to mean
that the idea is stupid. Is that impolite? What should I say to
express that a certain idea is stupid while keeping it polite enough
for this context? I understand that saying someone is stupid is not
polite but, at least in my native language/culture, saying the same
about abstract entities is fine.
However, I disagree with "there is no difference". There are changes
that don't change the manifest interface (i.e. the interface you
expose for the compiler, the function signature) but that do change
the actual interface. An example of that would be adding a check for
negative or otherwise out-of-range numbers in an integral property and
behaving differently for those (be it setting it to zero, or throwing,
or whatever). The actual interface becomes more than the signature,
because C++ does not have the capabilities to express richer
interfaces easily.
If you look at it in standards terms, the interface of a function is
not only the signature but also its Requires clause (and all the other
stuff but Requires is enough for this discussion).
Basically, I prefer when a change to the actual interface reflects
itself on the manifest interface, so that the compiler can help me
out. I am aware that this isn't so feasible, but that doesn't mean we
should add more ways to give up on that ability (I don't want to claim
it means we should not add them, though).
The use of the word "check" led me to think of changes similar to the
example I gave of checking for out-of-range values (locking a mutex is
not a check, is it?).
Changing normal data to properties with
additional "checks" in it is not something one wants to encourage.
Thanks for clarifying what you meant and I hope you will be more
precise about what kind of changes you want to enable with this
feature in the future, especially because I see a lot of programmers
thinking of this ability to add precondition checks silently as a
benefit of property syntax (that was all over the place when I was
using C#).
I find this uncompelling, because such transformations can easily break correctness. If someone expects the call to count() to return the same value in two successive calls (which might not even be in the same function), this transformation breaks them.
In practical terms, I've found it incredibly rare to make these kind of wholesale changes to implementations (those that change preconditions or postconditions) without having to revisit the entire program.
What problem is trying to be solved with properties? Is it just the syntactical notation of not having to use parentheses?
What problem is trying to be solved with properties? Is it just the syntactical notation of not having to use parentheses?
More or less. I belive the point of properties to be about allowing both member object and member functions to be used in the same way
so that one could be upgraded to the other when the need come, without having to modify the whole code base.
prop.set(c);
a = prop.get();
auto tmp = prop.get();
tmp += a
prop.set(tmp);
T(Class::*)() != void(Class::*)(T)
Has anyone considered using "auto" as a qualifier to specify that a function is a property?The D programming language uses a similar approach, except that "@property" is used in front of the function. The "property" keyword is already in use in Objective-C++ and CLI, so instead, the auto keyword could be used as a qualifier.I remember reading a paper somewhere that suggested something similar to this, but it used a new keyword "implicit" in place of auto. I believe this still clear enough, and avoids the need for another keyword.
class Test
{
int _number;
std::pair<int, int> _twoNumbers;
public:
// getter
int number() auto {
return _number;
}
// setter
int number(int number) auto {
return _number = number;
}
// getter by reference
const pair<int, int> &twoNumbers() const auto {
return _twoNumbers;
}
// setter
const pair<int, int> &twoNumbers(const pair<int, int> &tn) auto {
return (_twoNumbers = tn);
}
};
/////////////////////////
Test test;
test.number = 5;
//same as: test.number(5);
int a = test.number;
// same as: int a = test.number();
test.number += 5;
// same as: test.number( test.number() + 5 );
int a = 1 + test.number + 3;
// same as: int a = 1 + test.number() + 3;
cout << number.twoNumbers.first << endl;
// same as: cout << number.twoNumbers().first << endl;
Can we please name a property what it is - a *property*? I honestly don't care about other languages, C++ is not Objective-anything or CLI. I do not see any reason to use auto or any other new keyword.Those languages aren't compatible with C++ - neither should C++.
--