Properties Syntax

448 views
Skip to first unread message

Nick

unread,
Aug 27, 2013, 11:04:42 AM8/27/13
to std-pr...@isocpp.org
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;

Daniel Krügler

unread,
Aug 27, 2013, 11:24:45 AM8/27/13
to std-pr...@isocpp.org
2013/8/27 Nick <nicolas.j...@gmail.com>:
> Has anyone considered using "auto" as a qualifier to specify that a function
> is a property?

I'm not aware of anyone.

> 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.

It could, presumable, but IMO the syntax becomes easy to mix-up with
auto return types. I would prefer a clearer difference. Among other
choices, C++ could introduce a contextual keyword "property" (or
"auto_property") than can only be used in way that is syntactically
different from CLI.

- Daniel

Sean Middleditch

unread,
Aug 27, 2013, 12:49:24 PM8/27/13
to std-pr...@isocpp.org
C++ does not need properties.  It needs reflection capabilities to give the benefits of properties, but the language is already _far_ more flexible than any new property syntax could allow.

A property system needs to deal with multiple types of return values, multiple types of parameters, cv-qualified functions, etc.

The problem with C++ is not that we lack an easy way to define properties (we have it, and the STL even uses it, see below), but that there is no way to group all the functions of a property together logically for serialization systems and the like.

class my_type {
  std::vector<int> _foo;
public:
  const std::vector<int>& foo() const { return _foo; }
  my_type& foo(std::vector<int>&& v) { _foo = std::move(v); return *this; }
  my_type& foo(const std::vector<int>& v) { _foo = v; return *this; }
};

my_type mt;
// getter
auto v = mt.foo();
// setters
mt.foo(v);
mt.foo(std::move(v));

Note that the existing C++ approach avoids all the nastines of "is this a plain old data member or a property that does a bunch of work behind my back?" problem that C# suffers from.

Richard Smith

unread,
Aug 27, 2013, 2:41:38 PM8/27/13
to std-pr...@isocpp.org
#include <functional>
#include <utility>
#include <iostream>

template<typename T> struct property {
  std::function<T()> get;
  std::function<void(T)> set;

  property(const property&) = delete;
  property(property&&) = delete;
  property &operator=(const property&) = delete;
  property &operator=(property&&) = delete;

  operator T() { return get(); }

  template<typename U>
  property &operator=(U &&u) { set(std::forward<U>(u)); return *this; }
};

class Test {
  int _number;
  std::pair<int, int> _twoNumbers = { 3, 4 };

public:
  property<int> number = {
    [&]() { return _number; },
    [&](int number) { _number = number; }
  };

  property<std::pair<int, int>> twoNumbers = {
    [&]() { return _twoNumbers; },
    [&](const std::pair<int, int> &tn) { _twoNumbers = tn; }
  };
};

int main() {
  Test test;
  test.number = 5;
  int a = test.number;
  std::cout << test.twoNumbers.get().first << " " << a << std::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/.

Daniel Krügler

unread,
Aug 27, 2013, 3:30:55 PM8/27/13
to std-pr...@isocpp.org
2013/8/27 Richard Smith <ric...@metafoo.co.uk>:
Nice example! The expressiveness of the language is really great, but
I suspect that the outcome of the following expression test:

decltype(test.number)

is one of the main reasons why several people have been asking for
properties expressed by a core language construction instead of a
library solution. I guess that no-one seriously would want to change
decltype to make above type query return 'int'.

Just my personal opinion: I had worked quite a long time with Delphi
(to my knowledge one of Borland's main language architects were
involved in large parts with the language design of C# much later),
and it provided properties very early. It was great, because it was
natural to use them combined with the IDE. In C++ I seriously never
missed them not to exist, my guess is, because of the lack of this
kind of integration. But maybe I had not considered to use them in
other contexts than as members of classes. Maybe they could be useful
even in namespace scope when a could be used to make a function call
look like an object expression? (E.g. for constants)

- Daniel

nicolas.j...@gmail.com

unread,
Aug 27, 2013, 3:46:12 PM8/27/13
to std-pr...@isocpp.org, nicolas.j...@gmail.com
First of all, I appreciate everyone taking the time to respond. However, I still stand by my suggested implementation of properties.

Daniel,

  I do agree that there is a small chance for a mix-up, but any new language feature would introduce some kind of learning curve. Considering the current usage of const, virtual, default, and delete, I think that the relative complexity of a second usage of auto is very low, due to the fact that the current usage of 'auto' is very localized(used only in the place of a type).

  Also, I do agree that giving properties their own contextual keyword would be ideal, but considering that a new keyword may break existing code, I would favor using 'auto', because less conservative proposals for properties have already been rejected. Also, aside from the actual meaning of 'property' in Objective-C++ and CLI, there are many library based implementations(Like Richard's) which are called 'property'.


Sean,

  Properties are meant to aid in encapsulation, and code readability. Reflection is unrelated to this issue.

  Saying that "C++ doesn't need properties" is like saying "C++ doesn't need lambda functions" or "C++ doesn't need range-based for loops", There are many cases where properties would allow for cleaner code that is easier to read, and easier to write.

  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.

As far as why not to have properties:

I am not suggesting the C# property syntax. (in response to your recent blog post)
The method outlined in my original post does account for multiple return types, multiple parameter types, and cv-qualified functions through overloading.

I have seen the argument about properties hiding complexity many times, and it's still wrong. In a managed language like C# or Java, I might be concerned about abusive use of complex properties, because of the way that the language is designed to be used, but I am sure that the C++ community could handle them just fine. And if someone was careless enough to be bitten by complex properties, I would be much more worried about them forgetting to call delete on their raw pointers, or trying to implement concurrency.

Above all, the complexity is not hidden. All properties would be clearly marked as such in the header file, and provide the same guarantee about their complexity as would a function. And when the situation arose that a property was unusually complex, it could simply be omitted the same way that the standard omits the std::forward_list::size(). The declaration syntax I am suggesting also looks like a function, yet another clue about it's complexity.

And for serialization, C++ properties would not provide any complication that doesn't already exist in a class with functions-properties.


Richard,

The library approach is already well known, and suffers from several problems:
-memory usage
-extra indirection
-more complicated syntax
-inability to use them in all cases that a variable would be allowed

And even though your code is relatively clean, the compiler couldn't optimize it much without changing the observable size of the object.



Please say say If I have failed to comment, or misinterpreted any of your concerns,

  Thanks

Daniel Krügler

unread,
Aug 27, 2013, 3:49:51 PM8/27/13
to std-pr...@isocpp.org, nicolas.j...@gmail.com
2013/8/27 <nicolas.j...@gmail.com>:
> Also, I do agree that giving properties their own contextual keyword would
> be ideal, but considering that a new keyword may break existing code,

Could you please explain the risk of code breakage assuming a
contextual keyword? (If you have macros in your mind, I would agree,
but at the moment I don't think you mean them here).

- Daniel

nicolas.j...@gmail.com

unread,
Aug 27, 2013, 4:42:32 PM8/27/13
to std-pr...@isocpp.org, nicolas.j...@gmail.com
Daniel,

Actually, you are correct. I was mistaken about the usage of contextual keywords. But if another keyword were to be introduced, I don't think property would be the best candidate because of it's varied usage in different dialects of C++.

Objective-C++:
@property (getter=getNumber) int number;

C++ CLI:
property int number { int get() { return x; } }

GCC also has __attribute__ (alias (...)); which I believe can be used like a property.


auto_property as a contextual keyword would be fine by me though.

I also wonder if anyone would consider 'auto_' to be indicative of the possible performance implications.

Thiago Macieira

unread,
Aug 27, 2013, 4:48:44 PM8/27/13
to std-pr...@isocpp.org
On terça-feira, 27 de agosto de 2013 13:42:32, nicolas.j...@gmail.com
wrote:
> auto_property as a contextual keyword would be fine by me though.
>
> I also wonder if anyone would consider 'auto_' to be indicative of the
> possible performance implications.

Given past extensions, I guess we would choose a property with no "_" in the
name. From C++11 language extensions, the only place where I remember seeing _
was in attributes (carries_dependency) and even then it was not in all cases
([[noreturn]]).

So, given the precedent created by "noexcept" and "constexpr", I believe the
keyword should be "autoprop". :-)

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

Gabriel Dos Reis

unread,
Aug 27, 2013, 4:59:52 PM8/27/13
to std-pr...@isocpp.org
Thiago Macieira <thi...@macieira.org> writes:

| On terça-feira, 27 de agosto de 2013 13:42:32, nicolas.j...@gmail.com
| wrote:
| > auto_property as a contextual keyword would be fine by me though.
| >
| > I also wonder if anyone would consider 'auto_' to be indicative of the
| > possible performance implications.
|
| Given past extensions, I guess we would choose a property with no "_" in the
| name. From C++11 language extensions, the only place where I remember seeing _
| was in attributes (carries_dependency) and even then it was not in all cases
| ([[noreturn]]).

or static_assert.

| So, given the precedent created by "noexcept" and "constexpr", I believe the
| keyword should be "autoprop". :-)

is that for something that propulses itself?

Sean Middleditch

unread,
Aug 27, 2013, 7:31:26 PM8/27/13
to std-pr...@isocpp.org, nicolas.j...@gmail.com
On Tuesday, August 27, 2013 12:46:12 PM UTC-7, Nick wrote:
 
  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.

No, the case for properties in Java, C#, C++/CLI, Objective-C, and D is made.  The case for them in C++ is not.

That a great many people would adopt them is also not an issue.  A great many people would adopt eval() if it were somehow added.  Doesn't make it automatically a great idea.  You need to prove properties are actually beneficial in some way besides "hey, those other guys did it and some people like it."

You'll also need to think about issues like how property overriding/hiding interacts (with and without virtual), and how overloading interacts (can I define three different setters for the same property?), what taking the address of a property means (address of the getter?  of the setter?  which one?), how you can directly access a getter or setter as a method for template metaprogramming, etc.  This is not a trivial set of problems to solve.  They're solvable, but realize you'll need to do that to make a decent proposal paper for the committee.

Nick

unread,
Aug 27, 2013, 8:23:07 PM8/27/13
to std-pr...@isocpp.org
Sean,

I don't see a problem with a property behaving exactly as a regular getter/setter function with respect to hiding, overriding, overloading, etc. They are basically declared as functions, but with an extra keyword modifying them, and I think it would be counter-intuitive to implement their declaration in any other way.

The difference with properties, would be how they behaved in code. They would behave mostly like a variable, but with one restriction. At each instance where a variable would be retrieved or stored, the respective overload of the getter or setter would be called instead. If the address of a property was taken, it would be equivalent to taking the address of a function. Unless the return type was a reference, the behavior exhibited would be that of taking the address of a temporary returned from a function.

In terms of interaction with templates, I don't see any reason they couldn't use the same syntax as functions, but without the braces "()". The same rules for template deduction of a function parameter would apply to the right hand side of a property assignment.

For example,
object.property = 5; // deduced as int
int a = object.property<int>; // if a templated getter was declared.


I don't think that specifying the semantics for a property are trivial, but I don't believe they are a journey into the unknown either. The semantics of the language have already been decided, and a property would be nothing more than a mixture of the semantics of a function declaration, and the semantics of variable usage, with a small overlap of the function semantics towards the side of usage.

If the time came for me to write a proposal, I am confident I could describe the semantics of properties in full.


Could anyone with compiler experience comment on the difficulty of implementing something like this?

Bengt Gustafsson

unread,
Aug 28, 2013, 3:47:00 AM8/28/13
to std-pr...@isocpp.org
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).


Personally I am so entrenched with C++ that I don't really understand
how property syntax would improve the world, but if it is to enter the
language it seems that it can be done without adding keywords or
additional messy declarations in the headers. I do think that my
suggested approach could have some inherent dangers that I don't see
right now, especially the getter part of it.

Even if properties implemented like this could be parsed unambiguously
there is also the risk of too little redundancy: If every possible
combination of letters has a valid meaning there will be no error
messages to warn you when you are doing the wrong things with unexpected
results.

--
Bengt Gustafsson
CEO, Beamways AB
Westmansgatan 37A
582 16 Link�ping, Sweden
+46 13 465 10 85
www.beamways.com

Ville Voutilainen

unread,
Aug 28, 2013, 4:12:33 AM8/28/13
to std-pr...@isocpp.org
On 28 August 2013 10:47, Bengt Gustafsson <bengt.gu...@beamways.com> wrote:
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).



This would nicely take care of using properties, but the usual lure of properties in other languages is that
they are very easy to define, too.

Bengt Gustafsson

unread,
Aug 28, 2013, 7:50:04 AM8/28/13
to std-pr...@isocpp.org
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; }
    }
}

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:

class TimePeriod {
public:
    double Hours() { return seconds / 3600; }
    void Hours(double value) { seconds = value * 3600; }

private:
    double seconds;
};
--
 
---
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

corn...@google.com

unread,
Aug 28, 2013, 8:32:21 AM8/28/13
to std-pr...@isocpp.org


On Wednesday, August 28, 2013 1:50:04 PM UTC+2, Bengt Gustafsson wrote:
Do they really have syntax which is significiantly simpler than the classic setter/getter pair of C++?

Properties are about the usage syntax, not the declaration syntax. 

Ville Voutilainen

unread,
Aug 28, 2013, 8:00:32 AM8/28/13
to std-pr...@isocpp.org
On 28 August 2013 14:50, Bengt Gustafsson <bengt.gu...@beamways.com> wrote:
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; }
    }
}

Take a look at http://msdn.microsoft.com/en-us/library/bb384054.aspx for "auto-implemented properties". Those
are rather shorter when there's no need to customize the get/set operations.


Ville Voutilainen

unread,
Aug 28, 2013, 9:42:25 AM8/28/13
to std-pr...@isocpp.org
If that's the case (with which I disagree), we certainly don't need any language changes for
properties, since public non-static data members of reference or proxy class type achieve
the usage syntax just fine.

Sean Middleditch

unread,
Aug 28, 2013, 1:00:20 PM8/28/13
to std-pr...@isocpp.org
On Tue, Aug 27, 2013 at 5:23 PM, Nick <nicolas.j...@gmail.com> wrote:
> Sean,
>
> I don't see a problem with a property behaving exactly as a regular
> getter/setter function with respect to hiding, overriding, overloading, etc.
> They are basically declared as functions, but with an extra keyword
> modifying them, and I think it would be counter-intuitive to implement their
> declaration in any other way.
>
> The difference with properties, would be how they behaved in code. They
> would behave mostly like a variable, but with one restriction. At each
> instance where a variable would be retrieved or stored, the respective
> overload of the getter or setter would be called instead. If the address of
> a property was taken, it would be equivalent to taking the address of a
> function. Unless the return type was a reference, the behavior exhibited
> would be that of taking the address of a temporary returned from a function.

No, you need _way_ more than one modification.

They break usage of things that look like member variables everywhere.
Many simple templates, macros, and other libraries that make a simple
logical assumption like "std::addressof(x.y)" gives you the address of
x.y, which with properties could be the address of a temporary
returned by x.y(). Yuck.

Again, the problems could be solved with some additional work, but
that work needs to be thought through. Given an `x.y` kind of
expression, how can you tell if it's a property? Do we need a whole
new set of traits like is_field_assignable, is_field_readable, etc.?
What do mutating assignment operators like += do with a property; not
work at all, or expand out into separate get/set, or intelligently
determine if the property getter returns a reference or a type with an
overloaded +=? How do properties interact with N3617 (Lifting
Overload Sets into Function Objects) ? Do properties work in method
bodies and how to they interact with two-phase name lookup if at all?
What about properties and setters with more than one parameter and
initializer lists? Member initializers? etc.

>
> If the time came for me to write a proposal, I am confident I could describe
> the semantics of properties in full.

Go ahead and do it then. :) This forum is not some kind of gateway
to being allowed to write a paper. A good number of the people who
post here (myself included) are not part of the committee and have
_zero_ say on what goes into the standard.

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. :)

Ville Voutilainen

unread,
Aug 28, 2013, 1:17:52 PM8/28/13
to std-pr...@isocpp.org
On 28 August 2013 20:00, Sean Middleditch <se...@middleditch.us> wrote:

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. :)



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?

Magnus Fromreide

unread,
Aug 28, 2013, 3:13:26 PM8/28/13
to std-pr...@isocpp.org
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


Nick

unread,
Aug 28, 2013, 3:52:48 PM8/28/13
to std-pr...@isocpp.org
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.

Ville Voutilainen

unread,
Aug 28, 2013, 4:22:04 PM8/28/13
to std-pr...@isocpp.org
On 28 August 2013 22:52, Nick <nicolas.j...@gmail.com> wrote:
I have to disagree with this.

With Richard's implementation, taking sizeof(property<int>) yields 48 bytes.

Very likely, it's using std::function which is not the lightest or fastest thing on the planet.
 


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.



Well... I have no trouble making the functions smaller, just by avoiding std::function. The trouble with such
solutions is that I would need a combination of an auto member and a maker function (the call to which would be
a non-static data member initializer) to make it really palatable.

I can store data inside a property, avoiding the "reference to the container".

The library approach is not without downsides, but some of them are fixable. At any rate, fixing those downsides
would be worth trying before we run head-over-heels towards standardizing property keywords.

Richard Smith

unread,
Aug 28, 2013, 5:24:44 PM8/28/13
to std-pr...@isocpp.org
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.
 
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


Nick

unread,
Aug 28, 2013, 6:30:18 PM8/28/13
to std-pr...@isocpp.org
On Wednesday, 28 August 2013 17:24:44 UTC-4, Richard Smith wrote:
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.
 


There are several more problems with library properties beside the storage overhead.

Let's consider that we used the following template implementation, which still takes 4 bytes per property:

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; }
}

1) But consider using it on a Point:

struct Point
{
   
float x, y;
    Point(float x = 0, float y = 0) : x(x), y(y){}
};

How would you provide access to the members of Point with library properties?

struct Test {
    property
<Point, ...> point;
};

Test test;
cout
<< test.point.x << endl;

Currently, the only option available is to override T* operator->()

const T* property::operator->() { return &(object->*get)(); }

but unless C::get() returns a reference, which it very likely won't, then this code will be returning a reference to a temporary. This may not cause problems, since that temporary is read only, but may will fail to compile or generate warnings on some compilers.

2) No function overloading could be done for the setter.

3) specific functionality of the property's type would be hidden:

Consider if Point had operator+=()

Point& operator+=(const Point &p) { x += p.x; y += p.y; return *this; }

The following code would not compile:

test.point += Point(5, 6);

Whereas, with a real property, the get and set methods of the property could be called to retrieve and store the value.

Now, a partial solution may be to include commonly used operators inside the property class:

template<typename U>
property
&operator+=(U &&u) {
    T tmp
= (object->*get)();
    tmp
+= u;
    (object->*set)(std::forward<U>(tmp));
    return *this;
}

And since this is a template, I'm pretty sure(vs2012 and mingw tested) it should be ignored for classes that don't have an operator+= unless you actually try to use it, but that doesn't fix the problem that you still have to include every operator manually into your property class.

If you started to use a class that had a ToString() method, now you would need to incorporate that into your property too, and the list would go on endlessly.

4) Finally if something like offsetof() was standardized to work on non-POD types, there would be a way to get rid of that last 4 bytes per property, but currently, it is not. And I say "something like" because assuming that offsetof() did work, it would still require macros to get the job done. A real piece of builtin compiler magic would still be needed to get a pointer to the enclosing instance of an object.


Now, this is just the begining, but I'm sure I could go on for a few more hours at least.

Nicol Bolas

unread,
Aug 28, 2013, 7:04:06 PM8/28/13
to std-pr...@isocpp.org

I dislike properties in general. I don't like the idea of hiding function calls in such a non-obviously-calling-a-function way.

However, I feel that if we decide that properties are important enough to support, then they're important enough to support at the language level. This notion of hacking a "solution" via the standard library is just awful. I mean, look at this:


  property<int> number = {
   
[&]() { return _number; },
   
[&](int number) { _number = number; }
 
};

This is a massive hack and everyone who reads that knows it. The use of lambdas for what ought to be a simple function declaration, the use of a variable for what is clearly a pair of functions, etc.

Just look at this conceptually. You're initializing the `number` property. But you're not initializing it with its value; you're initializing it with some lambda functions. That's conceptual nonsense that reveals the hack for what it is. Rather than initializing the property with a value, you're just initializing a class with some functions. This makes no intuitive sense to anyone who doesn't understand how `property` works, thus forcing people to use it via cargo-cult copy-and-paste programming. Because that's always good.

Properties are supposed to make the language simpler easier to use, right? So why would anyone use this library feature that is difficult to work with, fidgety, bloats your class with pointless variables, confusing to read without someone explaining how it works, instantly turns any trivial type into a non-trivial type (since the property must be initialized by a constructor), instantly turns any standard-layout type with private members into a non-standard-layout type (since the property will be public), and is all-around a bad idea? Just to make talking to instances of the class slightly more convenient?

And this entire concept falls apart completely when a user tries to do any of the following very simple things:

decltype(test.number);
auto num = test.number;
std
::find(..., test.number);
//etc

And there's no way to work around that without some generalized way for a type to say "deduce me in all cases as some other type." And while I would be in favor of such a language feature (though not as a fix for this), there will be many such places where the abstraction breaks down and the kludge will make itself known.

If properties are syntactically a good and wanted thing, then they deserve the dignity of being a proper language feature. And if they aren't worth having as a first-class language feature, if they're not worth the standards committee's time and effort, they're definitely not worth having as a naked and transparent library kludge.

Half of a cat is not half as good as a whole cat. Having a library hack is worse than not having properties at all.

Loïc Joly

unread,
Aug 28, 2013, 7:41:36 PM8/28/13
to std-pr...@isocpp.org, Ville Voutilainen
Le 28/08/2013 15:42, Ville Voutilainen a �crit :
>
>
> If that's the case (with which I disagree), we certainly don't need
> any language changes for
> properties, since public non-static data members of reference or proxy
> class type achieve
> the usage syntax just fine.
>

The main problem I have with public data members implementing auto
properties is that they don't provide a migration path if later, we
decide to use a non-auto property.

---
Lo�c

Nick

unread,
Aug 28, 2013, 7:49:45 PM8/28/13
to std-pr...@isocpp.org, Ville Voutilainen
could you clarify what you mean by non-auto property?


On Wednesday, 28 August 2013 19:41:36 UTC-4, Loïc Joly wrote:
Le 28/08/2013 15:42, Ville Voutilainen a �crit :
Lo�c

Klaim - Joël Lamotte

unread,
Aug 28, 2013, 8:06:34 PM8/28/13
to std-pr...@isocpp.org, Ville Voutilainen

On Thu, Aug 29, 2013 at 1:49 AM, Nick <nicolas.j...@gmail.com> wrote:
could you clarify what you mean by non-auto property?

I believe Loic means that if I have a initial version of some code that look like this:

struct K
{
    int count;
};

int f( K& k )
{
   return k.count;  
}

Then (years) later I upgrade it with some checks using some property syntax, but want to keep the retrocompatibility:

class K // another retrocompatible change
{
public:
    
    property int count { //* */ }

}

Assuming the property works like a public variable, then this is useful.

However, if I started my code like this, as a lot of code does:

struct K
{
    int count();
};

int f( K& k )
{
   return k.count();  
}

Then there is no benefit in upgrading to properties, because it will not be retro-compatible.

I don't have an opinion on this point. However it might point that a property feature without
a way to implicitely use member functions like if they were properties (as some suggested) would not use useful for code
that is already written.

It feels a bit like allowing k.count() to be written count(k) : it might help generalization, but only with new code.


Joel Lamotte

Nick

unread,
Aug 28, 2013, 8:18:11 PM8/28/13
to std-pr...@isocpp.org, Ville Voutilainen
If I understand correctly,

while std::vector is currently implemented like this:

vector<T> {
    size_t size
() const { return _last - _first; }
};

and the size can be taken like this:

vector<int> myVec;
size_t sz
= myVec.size();

then you are saying that the implementation of vector should be able to be upgraded to:

vector<T> {
    auto_property size_t size
() const { return _last - _first; }
};

and still allow for both usages?

vector<int> myVec;
size_t sz1
= myVec.size();
size_t sz2
= myVec.size;

If this is correct, then I agree completely, and I think that this is feasible using the function based property syntax that I initially proposed.
 

Ville Voutilainen

unread,
Aug 28, 2013, 8:59:49 PM8/28/13
to std-pr...@isocpp.org
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?

Nick

unread,
Aug 28, 2013, 9:42:52 PM8/28/13
to std-pr...@isocpp.org
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?

Ville Voutilainen

unread,
Aug 29, 2013, 1:25:50 AM8/29/13
to std-pr...@isocpp.org
Depends on how far people are willing to go with reflection. ;) One of the expectations of people proposing
reflection facilities is that
1) 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 then

X x;
int foo = x.x;

or more verbosely,
X x;
int foo = std::reflection::member<compiletimestring("x")>(x);

Nicol Bolas

unread,
Aug 29, 2013, 2:54:53 AM8/29/13
to std-pr...@isocpp.org
On Wednesday, August 28, 2013 10:25:50 PM UTC-7, Ville Voutilainen wrote:
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 that
1) 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.

If reflection were a sure thing, if there was a proposal with broad support that had all of these necessary features in it, I could see that being a legitimate argument. Depending on the details of course; if you have to do what you did in your example, I'd still be against it (because that's horrifically unmaintainable in any real class). But without any such thing, I see no reason not to have this.

It's the whole `array_ref` problem all over again. Because of what might have happened (and notably did not), C++14 will ship without an important and useful piece of functionality.

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 then

X 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 of code in any way palatable or maintainable?

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.

Ville Voutilainen

unread,
Aug 29, 2013, 3:04:16 AM8/29/13
to std-pr...@isocpp.org
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 that
1) 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

Correct. 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 then

X 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

In 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 mass

There'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 an

Because 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.
 
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.




I guess we can speculate until the cows come home, but what is necessary for any property proposal to go
forward is for such a proposal to exist, first of all. And it should take a look at the property proposals that
have been proposed before, lest it's just running in circles.

max...@gmail.com

unread,
Aug 29, 2013, 3:32:47 AM8/29/13
to std-pr...@isocpp.org
FWIW, I share the view that "auto" properties hijack code by hiding function calls behind usual "variable" access ( and things like output parameters show that c+++ variables and properties do not share the same store/access semantics ). If one really wants a way to think get/set pairs as "properties", why not just having operators giving an alternative function invocation syntax ? ( as all user definable operators essentially do BTW ), eg. something like ( pretending the parser wouldn't complain ):

x:y:z        --parsed as-->  x.y().z()
x := y := z  --parsed as-->  x( y( z ) )

Il giorno martedì 27 agosto 2013 17:04:42 UTC+2, Nick ha scritto:
Has anyone considered using "auto" as a qualifier to specify that a function is a property?

Nicol Bolas

unread,
Aug 29, 2013, 7:54:18 AM8/29/13
to std-pr...@isocpp.org
On Thursday, August 29, 2013 12:04:16 AM UTC-7, Ville Voutilainen wrote:
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 that
1) 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

Correct. 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.

*ahem*: "Do people think properties should be a language feature, when they are seemingly just one of the many

things compile-time reflection can provide?"

That 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.

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 then

X 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

In 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 mass

There'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 an

Because 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. Nor should we try to twist reflection into something that would make properties work. If it naturally evolves that way, fine. But we shouldn't try to make it do that.

Ville Voutilainen

unread,
Aug 29, 2013, 8:06:31 AM8/29/13
to std-pr...@isocpp.org
On 29 August 2013 14:54, Nicol Bolas <jmck...@gmail.com> wrote:
 
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 many

things compile-time reflection can provide?"

That 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.

Feel free to continue putting words into other people's mouths. That's a question, not a dismissal. Anything
else you read into it is your own paranoia.
 

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++.

There's no way? Based on what evidence? Has this been explored by some proposal I'm unaware of?
You may be right, which to me would indicate that properties aren't worth their cost, especially
if it's common that the get/set functions need to be written anyway to cover cases where they aren't
just trivial operations.

 

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 then

X 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

In 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.

Oh. I must admit I'm unaware of an existing property system that allows multiple setters.
 

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.

No. You can set thin air if you want, or return temporaries.


part that lets you have multiple properties with different types (say, an int and a float)? Or the part that makes this increasing mass

There'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.

I can declare multiple specializations for it, since it's a template. I also expect eventually to have a run-time counterpart
for it that will be called if none of the templates match. That would be the way to plug run-time reflection on top of it.
 

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.

If people choose to do that, it's up to them. It's not the fundamental technique.
 

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

Because 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?

You keep speaking of "hacks". The reason behind such a "hack" that is the programmable dispatch is the case
where you have N properties/members in a subobject, and you want your containing wrapper to mirror those.
With your properties, you'll write N properties. With reflection, you write a single dispatching function that forwards
the member query to the subobject.

 

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.

The real question is whether this 20% is important enough that a more general facility can't cover it sufficiently
well. And do read what Richard said, perhaps it would be better to make language changes that make properties
as library features more feasible, rather than just putting in a core language property feature.


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.

Again, based on what evidence/exploration? I'd like to see some actual analysis rather than sweeping statements.

MJanes

unread,
Aug 29, 2013, 9:41:46 AM8/29/13
to std-pr...@isocpp.org
FWIW, I share the view that "auto" properties hijack code by hiding function calls behind usual "variable" access ( and things like output parameters show that c++ variables and properties would not share the same store/access semantics at all ). If one really wants a way to think get/set pairs as "properties", why not just having operators giving an alternative function invocation syntax ? ( as all user definable operators do BTW ), eg. something like ( pretending the parser wouldn't complain ):

x:y:z        --parsed as-->  x.y().z(), that is making : a member zero-ary invocation operator
x := y := z  --parsed as-->  x( y( z ) ), that is making := a one-ary invocation operator

this would also allow generalizations going beyond properties, while retaining usual c++ variable semantics ...

Nick

unread,
Aug 29, 2013, 11:06:05 AM8/29/13
to std-pr...@isocpp.org
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 int
set float
2

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.

Ville Voutilainen

unread,
Aug 29, 2013, 11:55:48 AM8/29/13
to std-pr...@isocpp.org
On 29 August 2013 18:06, Nick <nicolas.j...@gmail.com> wrote:
"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 int
set float
2

Thanks.
 

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>()"




I never claimed it provides a better solution that a simple property syntax. The idea is more geared towards
forwarding and avoiding boilerplate when doing so. If the same facility can be used for properties, that's
just fine and dandy.

Do note that I am unaware of any reflection idea that would support differentiating getters/setters like
properties do, so making (or, if you want, twisting) reflection facilities support the functionality
that properties provide requires some amounts of work.

Nick

unread,
Aug 29, 2013, 12:26:20 PM8/29/13
to std-pr...@isocpp.org
I don't see how it ever could.

Reflection is about being able to examine code at run-time.

If a class has a function Foo(then one should be able to do this:
Object *object;
Class->GetType()->GetMethod("Foo")->Invoke(object);

Likewise, with a variable called 'number', one should be able to do:
Object *object;
Class->GetType()->GetField("number")->SetInt(object, 5);

So I don't understand how the above could ever be better than a regular old setter/getter function.
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.

Ville Voutilainen

unread,
Aug 29, 2013, 1:03:38 PM8/29/13
to std-pr...@isocpp.org
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. 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.

Nick

unread,
Aug 29, 2013, 1:21:07 PM8/29/13
to std-pr...@isocpp.org
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.

more specifically, you can read this:



Nick

unread,
Aug 29, 2013, 3:01:42 PM8/29/13
to std-pr...@isocpp.org
This paper, suggests the idea of implicitly callable functions:

What I am suggesting is overloadable, implicitly callable functions, with one parameter, that can be paired with the ones that are described in the above paper.

There was a post about properties on these boards about 6-7 months ago, where someone mentioned this paper, but no one commented on it. Beside that, I have not been able to find any reference to discussion or a formal proposal on this topic. Does anyone have anymore information about this?

Ville Voutilainen

unread,
Aug 29, 2013, 3:06:12 PM8/29/13
to std-pr...@isocpp.org
The paper seems to be from an era during which the committee didn't necessarily take/publish technical discussion
minutes. At least I didn't find such technical minutes in the following mailing or the one in which that paper
was published. I can ask the Evolution Working Group for whether anyone recollects what happened and why.

Ville Voutilainen

unread,
Aug 29, 2013, 3:08:07 PM8/29/13
to std-pr...@isocpp.org
Oh, do note that while that implicit-function paper has some similarities to properties, the problem it
presents has afaik been solved by variable templates in c++14.

Nick

unread,
Aug 29, 2013, 4:55:53 PM8/29/13
to std-pr...@isocpp.org
True that part of the first problem has been solved with variable templates =) The paper still uses an ICF to calculate and return the area of circle based on it's radius, which cannot be solved with variable templates, so I still believe the feature deserves serious consideration.


I can't say I agree with the paper's solution to the second problem though.

The paper provides a method of creating a setter by returning a filter class instead of the actual value. While this does create the desired functionality of a setter, and does so with out the memory overhead of a library based property implementation, it still presents some of the same problems.

Firstly, the declaration of the filter class does decrease the readability of the class declaration. I imagine it would be quite painful to deal with a class declaration containing 10+ of these filter classes.

Second, and probably most importantly, the return type of the property will be hidden from the caller. Intellisense would report the return type as the name of the filter class, rather than the actual type, and any documentation would have to explicitly state the return type, and hope that the caller knows what's going on with the filter class.

A solution could be to name the filters things like float_AreaFilter, but it would be impossible to enforce this, and would be only a marginal improvement. Alternatively, the caller would be stuck having to go and look through the implementation of the filter to find out what it actually returns.

Also, any hopes of compile time type deduction of the property would be lost.

Finally, as I described above, for the library property implementation, any operator overloads or implicit conversions would have to be explicitly defined inside each filter class. Of course, a solution would be to inherit a bunch of mixins with operator overloads, but this would only serve to decrease readability even more.


So I think that the accessors as described in the paper are a good start, but that the solution for mutators would be much improved by using overloadable, single parameter, implicitly callable functions.



Ville Voutilainen

unread,
Aug 29, 2013, 1:50:09 PM8/29/13
to std-pr...@isocpp.org
On 29 August 2013 20:21, Nick <nicolas.j...@gmail.com> wrote:

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.

I have read each and every post in this thread. We may draw different conclusions from those posts,
and that's fine.
 

"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.



And those take into use the c++11 features at hand? Richard has a pretty good starting point for a library
solution for properties. Has that been explored further, or has it just been dismissed off-hand?

Nick

unread,
Aug 29, 2013, 9:34:32 PM8/29/13
to std-pr...@isocpp.org
I have stated the main problems with library implementations several times in this thread, and if you can't already see how they apply to Richard's implementation, or any library implementation, and why they can't be solved with the current set of language features(even c++11/14), then I'm not sure where to start explaining. If I were writing an actual proposal, I would describe the issue in detail, but I don't see any reason to keep repeating myself here.

Plus, I agree with Nicol Bolas. If anything in the realm of properties is going to be standardized, it should be done right. There is no point standardizing some expensive, messy, partially functional, hack you can just find on google.

If anyone could provide any information on what became of N1611, It would be greatly appreciated.

Nicol Bolas

unread,
Aug 30, 2013, 5:35:49 AM8/30/13
to std-pr...@isocpp.org
On Thursday, August 29, 2013 10:03:38 AM UTC-7, Ville Voutilainen wrote:
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.

We aren't trying to "explore the library possibilities" because it's a waste of time. They fundamentally cannot work; not without significant cruft and limiting the utility of the functionality. I have no idea what "other possibilities" refers to. If you're talking about the reflection stuff, save it; that's not an actual feature of any standard, nor is it a proposed feature for any standard. It's the twinkle in some people's eyes; it doesn't count as a "possibility" since a non-existent proposal cannot be adequately evaluated.

The essential essence of properties, as a construct, is the effective transformation of these expressions (given `Type variableName`):

auto data = variableName.field;
variableName
.field = data2;

Into these:

auto data = variableName.SomeGetterFunction();
variableName
.SomeSetterFunction(data2);

This is what the feature is; if a properties implementation cannot do this, it is non-functional.

C++14, as a language, cannot do this. Not correctly. Not in all cases.

`variableName.field` is a variable name. It must be a variable name. Therefore, any C++11/14-based library solution, no matter how it is implemented, must ultimately put a member variable named `field` in `Type`. It won't be the type that `SomeGetterFunction` returns, but it must be some type.

Here is a short list of the holes that this creates in the abstraction:

* 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.
* Since `field` is a public non-static data member, it is not private. Therefore, your class cannot be standard layout if you want private variables too. Admittedly, this is not very important since you just broke whatever layout compatibility you might have had by putting a member variable there. But it's still there.
* Since `field` is a variable, it has a type. A type that is notably separate from the return type of the hypothetical `SomeGetterFunction`. The simple `auto data = variableName.field` completely breaks the abstraction by deducing the field's actual type, rather than the hypothetical return type.

There may be more, but this is enough. It doesn't matter how these are implemented; the mere fact that it's a variable is the problem. These failures of the abstraction cannot be fixed. Every library implementation will have these failures.

Not being able to be used on standard layout types is a complete deal-breaker as far as users are concerned. One of the most obvious uses for properties is on simple vector and point classes:

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;
};

Properties need to be able to work on this class. It needs to be able to take those getters and setters and make it look like this to the user:

vec3 vec(...);
vec
.x = 4;
auto data = vec.z;

Ignoring the question of whether such a class should even have accessors, every library solution will change the layout of this class. Every library solution will make the class no longer standard layout.

And that's not acceptable, because it is very important to the utility of this class that it remain layout-compatible with various interfaces. If it's not layout-compatible with a simple struct of 3 floats, then it simply cannot do its job. That's a fundamental part of its interface.

That is what makes this a hack, a kludge. The abstraction has many points of failure, and they're all very easy to hit. They confine the library "solution" to a far more limited range of utility.

If the user of a feature, especially one that exists to make coding more convenient, has to be constantly thinking about niggling issues like this, or to avoid their use in common circumstances, then this is clearly not an acceptable method of implementation. This is much like Boost.Lambda, where you frequently have to do things like use `boost::ref` and such to create reference wrappers for things.

And note that this analysis does not need to look at an implementation. Every pure-library implementation will have these faults. There are more that I could look at, but I hope I've made my point: there's nothing to be gained by looking at "solutions" that a priori cannot succeed in any meaningful way.


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?

Sure, they may have made reference to attempts to implement them. But none of them dwelled on them at any real length. Why? Because they knew a priori that there was no way to do the feature any justice without real, language-level support.

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?

If you don't like properties as a feature just say so. If you don't want properties as a langauge feature, just say so. You don't have to hide behind "make it work as a library, then we'll see". Just say, "it's pointless and I don't want to see it in C++;" it's that simple.

I think the reason you want this "exploration" of library implementations is that you don't want properties. Ever. What you want is to find all of the places where the kludge-implementation of properties fails. Then, like adding spackling paste to a crumbling wall, you will add random features to C++ so that the kludge won't fail there. And you'll keep adding "standard spackle" until the kludge-implementation of properties gets to some "well enough" point, by a completely and wholely arbitrary metric.

And then you'll use that as a justification for why we shouldn't have it as a real language feature.

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.

So why do you single this idea out?

Ville Voutilainen

unread,
Aug 30, 2013, 6:08:17 AM8/30/13
to std-pr...@isocpp.org
On 30 August 2013 12:35, Nicol Bolas <jmck...@gmail.com> wrote:

* 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.

Thanks, that's a good reason.



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?

Because the proposal says "this is how properties must be, and alternatives don't work". It has to explain why
the alternatives don't work.
 

No other proposals had to go through that. I don't recall Bjarne Stroustrup having to explore Boost.ConceptCheck before talking

Every one of them did. You're mistaking the level to which they went through that.
 
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

The static if proposal did sufficient exploration, and explains the motivation of static if as opposed to using #define
to do the same things. The "exploration" has never been suggested as a requirement to implement a library solution
as a prerequisite for proposing a language feature, although it wouldn't hurt.
 
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?

Before talking? No. I expect they should most certainly investigate the library solutions before proposing language
changes.
 
 
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?

There's nothing special about properties. The bar for them is the same as for other proposals. I don't think I have
requested anything that other proposals didn't do.
 
 
I think the reason you want this "exploration" of library implementations is that you don't want properties. Ever. What you want is to

I think the reason I want it is because I want the people who write a proposal for properties to provide evidence
for their assertions, and write up the reasons why they are proposing language changes instead of library
additions.

 

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.

They certainly didn't ignore the "library kludge". They considered how far a library solution can go and made an educated
decision. Furthermore, they wrote a proposal that explains the results of that consideration.
 

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.


That's just utter rubbish. The lambda proposal authors are the very same people who have written
boost lambda. They most certainly did go through boost lambda in the way you describe, and, again,
presented a proposal based on that analysis, after finding out that language changes are necessary.

Martinho Fernandes

unread,
Aug 30, 2013, 7:34:28 AM8/30/13
to std-pr...@isocpp.org, Ville Voutilainen
On Thu, Aug 29, 2013 at 2:06 AM, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
>
> On Thu, Aug 29, 2013 at 1:49 AM, Nick <nicolas.j...@gmail.com> wrote:
>>
>> could you clarify what you mean by non-auto property?
>
>
> I believe Loic means that if I have a initial version of some code that look
> like this:
>
> struct K
> {
> int count;
> };
>
> int f( K& k )
> {
> return k.count;
> }
>
> Then (years) later I upgrade it with some checks using some property syntax,
> but want to keep the retrocompatibility:

In my opinion this is quite stupid. Putting in some checks is a
breaking change and you want all code affected to continue compiling
silently? Or, in other words, what kind of checks can you put in that
are not a breaking change from what is effectively just a normal data
member?

Mit freundlichen Grüßen,

Martinho

Klaim - Joël Lamotte

unread,
Aug 30, 2013, 10:33:04 AM8/30/13
to std-pr...@isocpp.org, Ville Voutilainen

On Fri, Aug 30, 2013 at 1:34 PM, Martinho Fernandes <martinho....@gmail.com> wrote:
In my opinion this is quite stupid. Putting in some checks is a
breaking change and you want all code affected to continue compiling
silently? Or, in other words, what kind of checks can you put in that
are not a breaking change from what is effectively just a normal data
member?

First, that's a very simplistic example to show the evolution.

Second, no, that's not stupid (please stay polite), it's the kind of change you do each time you modify the implementation of a function without changing it's interface.
There is no difference: if you do a breaking change in your implementation, yes it will break the whole, but at least it's isolated in a specific scope.
It's totally different than changing an interface (why do I even have to explain this?) which will force the user to change a lot of code, and each change is an opportunity
to add new bugs, without the initial change being the source of the bugs.

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.
Here, either there is some kind of property feature that makes this code not impact the usable code, even if the type
itself becomes more complex, or you have to go to all the user code and modify it.
It DOES have an impact that might break the application, like ANY change to any implementation of an interface.
But here the problem pointed is the interface, the implementation is not the problem that properties is trying to solve.

Joel Lamotte

Martinho Fernandes

unread,
Aug 30, 2013, 11:50:21 AM8/30/13
to std-pr...@isocpp.org, Ville Voutilainen
I think I was misunderstood :( And maybe I misunderstood you as well.

On Fri, Aug 30, 2013 at 4:33 PM, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
> Second, no, that's not stupid (please stay polite),

Let me get this out of the way first. Even though people tell me I
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.

On Fri, Aug 30, 2013 at 4:33 PM, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
> it's the kind of change
> you do each time you modify the implementation of a function without
> changing it's interface.
> There is no difference: if you do a breaking change in your implementation,
> yes it will break the whole, but at least it's isolated in a specific scope.
> It's totally different than changing an interface (why do I even have to
> explain this?) which will force the user to change a lot of code, and each
> change is an opportunity
> to add new bugs, without the initial change being the source of the bugs.

Ok, even though, as you said, the example provided is a poor one, it
was enough for me to conjecture some hypothetical better ones.

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). The signature for
`std::sort` says it takes two iterators and a comparison (well, not
even that, but let's pretend it does), but that's not all. It takes
two iterators *that define a valid range* and a comparison *that
defines a strict weak ordering*. If, for example, you change "that
defines a strict weak ordering" to "that defines a total preorder" by
changing only the implementation, you will break your clients, even
though the manifest interface didn't change. Your clients will likely
still compile with such a change, but they will no wonder work
correctly.

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#).

Mit freundlichen Grüßen,

Martinho

Nevin Liber

unread,
Aug 30, 2013, 12:05:07 PM8/30/13
to std-pr...@isocpp.org
On 30 August 2013 09:33, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:


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.

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?
--
 Nevin ":-)" Liber  <mailto:ne...@eviloverlord.com(847) 691-1404

Klaim - Joël Lamotte

unread,
Aug 30, 2013, 12:06:30 PM8/30/13
to std-pr...@isocpp.org, Ville Voutilainen
On Fri, Aug 30, 2013 at 5:50 PM, Martinho Fernandes <martinho....@gmail.com> wrote:
On Fri, Aug 30, 2013 at 4:33 PM, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:
> Second, no, that's not stupid (please stay polite),

Let me get this out of the way first. Even though people tell me I
have a high level of fluency in English, it isn't my native language
so I apologise if I inadvertently crossed a line somewhere.


Not much, and I'm not a native english speaker either, but the "stupid" word is both hiding what you mean 
and not respectful.
 
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.



Saying something is stupid is not polite either.
Just state exactly what you find hard to accept and why, so that we can argue about it politely.

I must precise: I'm not offended, don't worry.
 
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).

Indeed.

Yes changing the implementation the way I suggest change the requirements,
but it don't change the interface itself.
I don't know if we can consider the requirements parts of the whole interface,
I think that in C++, until we have a standard way to check these requirements
other than by using strong typing, it's hard to consider an interface and it's
requirements as the same thing.
 
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).


As I was saying, I don't see how changing a requirement of a library interface can be
reflected on the compilation of user code.
The only way is to have something like contracts and assertions, but 
it's a totally different proposition (which someone is working on by the way).
 
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?).

The mutex example is not a check indeed.
The initial statement is similar to what you expected, so yes I was talking for example
checking if the returned value make sense or if the call itself is valid.
I could find another simple such example, like returning a normalized direction from such a property
but you get the idea.
 
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 meant any change that don't break the interface.
Unfortunately, as stated already, there is no way to, at compile time,
to enforce requirements at compile time or runtime other than what 
can be checked through strong typing, assertions and soon concepts.

What you suggests, if I understood correctly, is that the point of having properties
so that evolution of an interface is easy don't makes a lot of sense if there is no way
to enforce the requirements of the interface.
Tell me if I misunderstood.

If I'm correct, then I both agree and disagree: in a perfect world you would be right.
In the current C++ version, we change implementations all the time without changing interfaces,
sometime with changing the requirements too. I agree that a way to enforce requirements would 
make both properties and all function interfaces better.

Joel Lamotte

Thiago Macieira

unread,
Aug 30, 2013, 12:06:56 PM8/30/13
to std-pr...@isocpp.org
On sexta-feira, 30 de agosto de 2013 02:35:49, Nicol Bolas wrote:
> What you want is to find all of the places where the kludge-implementation
> of properties fails. Then, like adding spackling paste to a crumbling wall,
> you will add random features to C++ so that the kludge won't fail there.
> And you'll keep adding "standard spackle" until the kludge-implementation
> of properties gets to some "well enough" point, by a completely and wholely
> arbitrary metric.

And what's the harm in that? No, really, let's think this through.

If a solution can be achieved with just minor language changes supported by a
larger library change, should we not consider it against a major language
change? There are benefits to doing it with a minor language change, most
notably the fact that compilers will implement them more quickly and that
there's a smaller chance of incompatibilities. There may be cons too, like a
more clumsy syntax.

Also, "arbitrary metric" is exactly what you proposed on this email. You
listed a few requirements that any solution must meet. If a minor language
change + library change solution meets those requirements, why should it not
be considered?

Note that I'm not at all passing judgement on the properties language or
properties library proposals.

--
Thiago Macieira - thiago (AT) macieira.info - thiago (AT) kde.org
Software Architect - Intel Open Source Technology Center
PGP/GPG: 0x6EF45358; fingerprint:
E067 918B B660 DBD1 105C 966C 33F5 F005 6EF4 5358

Klaim - Joël Lamotte

unread,
Aug 30, 2013, 12:12:33 PM8/30/13
to std-pr...@isocpp.org
On Fri, Aug 30, 2013 at 6:05 PM, Nevin Liber <ne...@eviloverlord.com> wrote:
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.


I believe you are making the same point than Martinho Fernandes so I should have answered in my last email.
 
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.


It depends on the requirements but I also find rare a change of requirements by changing implementation of a function.
However, I don't always have checks that make sure I didn't change these requirements.
To me all these points are about the requirements part of any kind of function (properties included) which indeed are hard to prove not being changed by a change of the implementation.
But again, fixing that requires another set of language feature and is not directly related to properties, in my opinion.
 

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.

loic.act...@numericable.fr

unread,
Aug 30, 2013, 12:14:02 PM8/30/13
to Martinho Fernandes, std-pr...@isocpp.org, ville.vo...@gmail.com

---- Message d'origine ----
>De : "Martinho Fernandes" <martinho....@gmail.com>



> 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#).

There are two kinds of checks that may be added: 
- You might add a new precondition
- You might add a new check for an existing precondition that was previously only mandated in documentation, and for which you provided no help to the user if it was violated.

I believe the second use case is fine.

And even in the first situation, not having properties would force an interface change the first time a precondition is added, but all further changes to preconditions will be non interface breaking, unless you purposefully do it, which may be done by renaming the interface too.

Breaking the interface when the implementation evolves may be very beneficial in some cases, but I believe the benefits of it depends on the specific situation. It should be an explicit decision of the class designer to break the interface or not. Currently, changing the implementation may force the class implementer to break the interface(*). With properties, he would have the freedom to do what is best in his case.

I have several similar other use cases where I would probably not want to break the interface:
- Adding some instrumentation to the code, for instance logging all accesses to a data
- Switching between a data that is directly stored and a data computed on demand.


(*) In fact, in order to avoid the possibility of this forced interface breakage, many coding standards discourage the use of public data members, mandating code that is longer to write and less pleasant to use.

--- 
Loïc

Klaim - Joël Lamotte

unread,
Aug 30, 2013, 12:16:47 PM8/30/13
to std-pr...@isocpp.org



On Fri, Aug 30, 2013 at 6:12 PM, Klaim - Joël Lamotte <mjk...@gmail.com> wrote:


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.

I should add that, as pointed previously, one coudld have the same feature by just always using functions in public interfaces,
in which case indeed parentheses might become noise.

That's basically why I think properties are interesting but I'm not really pressed to have them in C++ (if there was a competition in order of inclusion in the standard).
I can still use member functions only as public interfaces and ignore the noise of the parentheses.
Still, if there was a simple and cheap way to remove that noise, it would be "nice".

Magnus Fromreide

unread,
Aug 30, 2013, 12:47:04 PM8/30/13
to std-pr...@isocpp.org
On Fri, 2013-08-30 at 18:14 +0200, loic.act...@numericable.fr
wrote:
I have a pile of such code myself, and sometimes properties feels like
an easy fix.

I then realize the the problem is that the code is written to an
interface that is at to low a level and the real fix is to abstract the
code further so that clients won't have to muck about with the internal
details of the classes.
>
> (*) In fact, in order to avoid the possibility of this forced
> interface breakage, many coding standards discourage the use of public
> data members, mandating code that is longer to write and less pleasant
> to use.
>
I think this is very much in the eye of the beholder - from my point of
view non-private data members are a wart on a class and papering over
them is not helpful. Furthermore, properties used in this way makes it
harder to reason about the code.

Can this throw?

instance.variable;

Today, the answer is no but with properties it might. Now, that might be
beneficiary in some odd cases but it is still surprising.

I also think that the function call

instance.variable;

is a lot less clear about being a function call than

instance.variable();

/MF


Bengt Gustafsson

unread,
Aug 30, 2013, 12:52:54 PM8/30/13
to std-pr...@isocpp.org
To me the latest motivation for properties is the most resonating: creating the ability to change a plain data member to a pair of methods in a later edition of a library component without breaking code. And I agree that a good effect of this would be that you don't have to do setters and getters for all members just in case that you may want to add checks or transformations or whatever later.

I previously posted the suggestion of introducing syntactical sugar at the place of use where assignment gets transformed to a setter call in basically the same way as a = in a declaration is transformed to at ctor call, and where mentioning a method pointer without the leading & is sugered to implicitly add a trailing().

The main drawback with this idea is probably that you have to use the pattern that the two methods have the same name with 0 and 1 parameter. To allow a = b = c syntax the setter would have to return the value set, otherwise you would end up with the rather strange:

int a = object.getTheProp;
object.setTheProp = 3;

The main advantage is that it does not add any burden to the writing of the class head, and (I think) that it is easy to implement for compiler vendors and safe as it only allows code that was previously erroneous.

When it comes to Ville's earlier (well, a lot earlier by now) comment about auto-implementing set and get methods, that's the other way around, isn't it? You declare a data member but access it as if it was a pair of setters in the code that uses the class. To me this seems like a way to reduce the typing burden which stems from the programming guideline rule that all member access is to be via setters and getters. Of course the two can be combined, which causes what looks like an assignment into a setter call which does the exact same assignment (with automatic implementation there's not much else it can do), all awaiting a possible future time when the setter may be replaced with an explicitly written function. Rather contrived (unless we are aiming at binary backwards compatibility - no recompilation required, but it doesn't seem so from recent posts).

The implications of using the value of a member variable and then the member variable gets replaced by a getter of the same name is normally that it just continues to work. But other uses like taking the address of the member no longer works. But how could it? There is no member to take the address of anymore. And thus the code should break. When you do a reimplementation for instance to calculate the value on the fly instead of storing it as a data member you must of course accept that you can't take its address anymore. decltype() is also a problem as it would change from the member type to the method type, or do you have to add the leading & to use decltype with a method?

There is of course the case when the getter you replaced the member with returns a reference to another member, which you then should be able to take the address of, but won't be as taking the address would get you the address of the method (a possibility we must of course preserve). This means that the code looks broken, so you have to add your trailing () again, but it doesn't get worse than that.

My conclusion is that this approach would solve a majority of the problem, be noisy about almost all remaining cases, but admittedly cause a few member->method changes to cause hard to track errors, such as getters that actually return method pointers or return values captured by auto followed by code that is indifferent to type. But given that a method pointer is about the weirdest type available in C++ (i.e. works with least amount of operators and function signatures) I think the actual cases of "silent breaking of code" will be very few. Note that I'm not talking about this language change breaking code (if someone can show that the language feature itself breaks ANY code I don't think it should be introduced). 

Bengt Gustafsson

unread,
Aug 30, 2013, 1:01:55 PM8/30/13
to std-pr...@isocpp.org
Magnus:

You are of course right that from a clearness standpoint a function call should look like one and a member access look like that.

So the question is whether this is more important than being able to migrate from variable to method without breaking existing usages.

I know that many think that global data members are a no-no, but isn't that a consequence of considering the possibility that checking of the value or action on its change may be needed in the future, and thus actually the only solution to the migration problem being promoted to a self-sufficient rule. Apart from the scare of future code breaking changes, why would setting a member by calling setters be better than setting it directly? At least this is the usual motivation for setters/getters I have seen in text books.

Magnus Fromreide

unread,
Aug 30, 2013, 1:46:26 PM8/30/13
to std-pr...@isocpp.org
On Fri, 2013-08-30 at 10:01 -0700, Bengt Gustafsson wrote:
> Magnus:
>
>
> You are of course right that from a clearness standpoint a function
> call should look like one and a member access look like that.
>
>
> So the question is whether this is more important than being able to
> migrate from variable to method without breaking existing usages.
>
I think that is one of the big questions here.

> I know that many think that global data members are a no-no, but isn't
> that a consequence of considering the possibility that checking of the
> value or action on its change may be needed in the future, and thus
> actually the only solution to the migration problem being promoted to
> a self-sufficient rule. Apart from the scare of future code breaking
> changes, why would setting a member by calling setters be better than
> setting it directly? At least this is the usual motivation for
> setters/getters I have seen in text books.
>
I do not think setters/getters are a good thing either, just that they
are better than public members but I admit that the reason they are
better is as outlined above.

The reason they are bad is that they expose internal parts of the
object, just like public members do.

I prefer if the code is at a higher level so I have a Square with two
constructors, one taking a distance and the other taking an area. When I
want to change my Square instance using either property i construct a
new Square and assign it to the original one.

Yes - sometimes this won't work but that is a problem for those times.

/MF

Message has been deleted

Nick

unread,
Aug 30, 2013, 2:28:05 PM8/30/13
to std-pr...@isocpp.org
Bengt:

Taking the address of a property should not create any new problems. Since properties would inherently be functions, taking their address would exhibit the same behavior as taking the address of any function, and that behavior is already described in the standard. That behavior shouldn't have to be changed to add properties.

My intention is that getter/setter pairs should be implemented as two methods which have the same name, with 0 and 1 parameter, but I don't see this as a drawback. It actually provides several advantages, one of which being the ability to overload the setter, and another being that the getters and setters are clearly declared as functions in the header, signifying the possibility of side effects to the caller.

I image the effect of 'a = prop = c' to be as follows:
prop.set(c);
= prop.get();

Likewise, I would expect 'prop += a' to work as follows:
auto tmp = prop.get();
tmp 
+= a
prop
.set(tmp);

I do agree there is the 'possibility' for confusion, but this exists with any feature, and I believe the above usage should be straight forward enough.

"here is of course the case when the getter you replaced the member with returns a reference to another member, which you then should be able to take the address of, but won't be as taking the address would get you the address of the method"

I don't see any reason that this should work differently than a regular function, and taking the address of an implicitly callable function that returns a reference should yield the same result as if the function was not implicitly callable.


"if someone can show that the language feature itself breaks ANY code I don't think it should be introduced"

I do agree, but as properties would inherently be "functions with perks" I don't believe they should introduce any major new problems.


Magnus:

"The reason they are bad is that they expose internal parts of the 
object, just like public members do."

I don't understand how this is the case, considering that an implementer could omit the setter function, only implementing the getter, thus making the property read only.

Thiago Macieira

unread,
Aug 30, 2013, 4:16:36 PM8/30/13
to std-pr...@isocpp.org
On sexta-feira, 30 de agosto de 2013 09:52:54, Bengt Gustafsson wrote:
> To me the latest motivation for properties is the most resonating: creating
> the ability to change a plain data member to a pair of methods in a later
> edition of a library component without breaking code.

That's assuming the rest of the code isn't doing anything like taking pointers
or references to the property itself.

For example, the following would break if Klass::theprop becomes a property
instead of a plain int:

void f(int &);
void f(Klass k)
{
f(k.theprop);
}

In some situations, it might be a good thing that it breaks. But it's still a
breakage.

In that light, I have to ask: has anyone given any thought to a "pointer-to-
member-property?" We have PMFs and PMDs, so what would be the syntax and the
requirements for a PMP?

Also, what happens to setter overloads in a PMP?

Klaim - Joël Lamotte

unread,
Aug 30, 2013, 4:30:06 PM8/30/13
to std-pr...@isocpp.org

On Fri, Aug 30, 2013 at 10:16 PM, Thiago Macieira <thi...@macieira.org> wrote:
For example, the following would break if Klass::theprop becomes a property
instead of a plain int:

void f(int &);
void f(Klass k)
{
    f(k.theprop);
}

Could you clarify how that would break?


Bengt Gustafsson

unread,
Aug 30, 2013, 5:46:57 PM8/30/13
to std-pr...@isocpp.org
The discussion lately has revolved around classes evolving from having data members to in later editions having equally named setters and getters, and in which cases this transition in one user defined library breaks other user defined code. If theprop in Thiago's example changes from a data member to a getter returning by value calling f for this value breaks.

Thiago: Under which condition would it NOT be good that your code example breaks. Well, maybe if f() really uses the parameter as a const&... do you see other cases?

Thiago(2): As per my suggestion properties are just syntactic sugar at the place of use there is no special PMP thingy. With other suggestions with special provisions in the class head this would be an important consideration, what you may have use for is to get the address of the setter and getter, but what you think you have is a data member... I would not even want to think about having a PMP which packetizes the getter and all setters into an "overloaded member function pointer" which can then be called in so many different ways...

Nick: In the same situation, what happens when the code evolves is that the address of the member goes from being a T* to a T (CLASS::*)(), which is rather a big difference.

Nick(2): The other assignment operators and serial assignment would be problematic, I think. Mainly as the result of copy construction followed by the operator followed by assignment may not render the same result as applying the operator on the "real" data, but also for performance reasons. Nevertheless, not having these operators automagically generated as you indicate will surely be the largest source of code breakages when evolving from a plain data member to setter/getter... anyone with better ideas?

Thiago Macieira

unread,
Aug 30, 2013, 6:18:14 PM8/30/13
to std-pr...@isocpp.org
On sexta-feira, 30 de agosto de 2013 14:46:57, Bengt Gustafsson wrote:
> Thiago: Under which condition would it NOT be good that your code example
> breaks. Well, maybe if f() really uses the parameter as a const&... do you
> see other cases?

If it's const ref, it's not a problem. The getter member will either return
(at minimum) a prvalue or a const-ref, both of which bind to a const-ref.

A very simple example is if that f(int &) overload did:

void f(int &i) { i = 2; }

Whereas before you could call this indirect setter, with properties you can't.

By the same token, the pointer to the data member will no longer compile:

int Klass:: *ptr = &Klass::theprop;
auto ptr2 = &Klass::theprop;

I'm sure we can find a few more if we think really hard.

The only reason I brought this up is that one of the stated benefits for having
a language extension to support properties was that it would allow updates
without source-incompatibility. That is not the case: some incompatibilities
might happen.

> Thiago(2): As per my suggestion properties are just syntactic sugar at the
> place of use there is no special PMP thingy. With other suggestions with
> special provisions in the class head this would be an important
> consideration, what you may have use for is to get the address of the
> setter and getter, but what you think you have is a data member... I would
> not even want to think about having a PMP which packetizes the getter and
> all setters into an "overloaded member function pointer" which can then be
> called in so many different ways...

Fair enough, I was just asking.
signature.asc

Nick

unread,
Aug 30, 2013, 6:44:07 PM8/30/13
to std-pr...@isocpp.org
I would not even want to think about having a PMP which packetizes the getter and all setters into an "overloaded member function pointer"

This would not have to be the case, but I understand how it may seem that way. For that reason, I should revise my original premise.

At this point, I don't even believe this concept should be referred to as properties. I believe the wording from N1611 is much more appropriate. I do not believe the word "Property" should be associated with this concept at all, because questions like the one I have quoted above will just keep coming up. I believe this issue should be labelled both in terminology, and in the C++ language as "implicitly callable functions". It should be clearly labelled as a language construct specific to C++, which has no explicit or implicit relationship to "properties" in any other language. And the contextual keyword "implicit" should be used to denote that a class member function can be implicitly called. These functions could be described as functions that are called implicitly as needed to facilitate the usage of an appropriately qualified identifier, where the get and set methods may be called one or more times in a single expression.

With the above revision in mind, the response to the original concern about function pointers becomes obvious:

T(Class::*)() != void(Class::*)(T)


"Nick: In the same situation, what happens when the code evolves is that the address of the member goes from being a T* to a T (CLASS::*)(), which is rather a big difference."

That is true, and yet another reason why I feel it's necessary to revise my original premise. I believe making it known that these are functions would allow the caller to make better judgement concerning their use.

"void f(int &i) { i = 2; } 
Whereas before you could call this indirect setter, with properties you can't."

This is also true, along with many similar cases, and it may make sense to create a list of attributes of regular functions that would be prohibited in the case of implicitly callable functions. I don't believe that placing a few restrictions on unnecessary use cases would hurt the overall usefulness of properties.

Nick

unread,
Sep 3, 2013, 10:00:05 PM9/3/13
to std-pr...@isocpp.org
  I have to say, I am surprised at the overall lack of enthusiasm for this idea.

  I think implicitly callable functions have great potential as a language feature, especially considering that they can be implemented in a completely backward, non-breaking way. I think that the argument about the "hidden complexity" of properties would turn out to be completely unfounded if their real use cases were examined objectively, and that any concerns about their negative impact on code coherency could easily be put to rest, given a sufficiently detailed specification of their behavior.

  I plan to write a draft specifying the details of implicitly callable functions, their semantics, their alternatives, and an analysis of some common use cases. I wouldn't feel like I had given this idea a fair shake without removing the complication that can arise when discussing such a complex issue piece by piece.

  I would like to thank everyone again for their contributions.



On Tuesday, 27 August 2013 11:04:42 UTC-4, Nick wrote:
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;

stackm...@hotmail.com

unread,
Sep 4, 2013, 3:06:10 AM9/4/13
to std-pr...@isocpp.org
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++.

Klaim - Joël Lamotte

unread,
Sep 4, 2013, 4:40:53 AM9/4/13
to std-pr...@isocpp.org
On Wed, Sep 4, 2013 at 9:06 AM, <stackm...@hotmail.com> wrote:
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++.

-- 


"Properties"  often use a specific syntax, here Nick is talking really about only allowing functions to be implicitely callable, nothing more.
"properties" suggests more.

Joel Lamotte
Reply all
Reply to author
Forward
0 new messages