Archived

This topic is now archived and is closed to further replies.

haro

Why aren't readonly and writeonly C++ Keywords?

Recommended Posts

Why was the concept of readonly/writeonly variables not included in C++? The idea is simple and useful. A readonly variable can only be written to by the class it is created within. A writeonly variable can only be read from the class it is created within. For example:

class Particle
{

public:

  Particle( double x, double xVelocity = 0 )
  {
    this->x = x;
    this->xVelocity = xVelocity;
  }
  
  void Update( double deltaTime )
  {
    x += deltaTime * xVelocity;
  }

  readonly double x;

private:

  double xVelocity;

}

void main()
{
  Particle p( 10.0, 1.0 );
  cout << "The particle is currently at x = " << p.x << endl;
  p.x = 12.0; // Compile Error, writing to a readonly variable

  cout << "The particle is now at x = " << p.x << endl;
  p.Update( 10.0 );
  cout << "The particle is now at x = " << p.x << endl;
}
This style would allow for easy and efficient C style data access since there is no function call overhead using C++ style data accessor functions. But at the same time you would maintain the safety and encapsulation C++ offers. Its win win. Writeonly variables would be similiar, only they would not be able to be read from. While likely not as useful as readonly, writeonly would definitely still have use. Namely in setting state variables of an object before updating that object and insuring proper adherence to the interface. There would be no reason to read variables which should be obsolete before updating the object, and with writeonly variables the object could insure this is an effective fashion without having to rely on potentially costly function overhead if the only ways to modify its state data was with tiny manipulator functions. This seems much more elegant and in the C++ spirit, rather than writing the 1-3 line functions and relying on the virtually undefined implementation of inline and the obfuscation its obscurities bring your code.

Share this post


Link to post
Share on other sites
Well, the function call overhead isn't really a problem because you can inline functions. Plus, for read-only variables you could use the const keyword so you wouldn't need accessor functions. Write only variables might be convenient sometimes, but since the functionality is so easy to get with accessor functions (inlined if necessary), there's not really any need for it. Also, a reason you give for needing write-only variables is for communicating across an interface but write-only variables expose implementation details of the interface b/c names and data types of all write-only variables would have to be the same across all implementations of the interface. So their utility would be very marginal.

[edited by - gurgi on July 8, 2003 1:03:50 AM]

Share this post


Link to post
Share on other sites
The idea of a read only variable is a variable that can be modified from within the context of the class that creates the variable. As the example program shows, if the readonly variable was changed to a const then the program would not compile since the update function CHANGES THE VALUE OF THE READONLY VARIABLE SINCE IT IS WITHIN THE SAME CLASS AS THE VARIABLE WAS DECLARED WITHIN.

Also, as mentioned. The idea was to get rid of pointless 1-3 line inline declarations scattered throughout your .h files. It looks silly. Ideally, I would like to have a header as a pure header. No implementations, just headers. This makes for easier reading, updating and maintenance of code. Not to mention that, also as mentioned, the implementation of inline is not truly defined. A compiler can do pretty much of anything it likes when it sees an inline in code, so you're not even sure if your 50 little functions are actually being inlined ( though admittedly, they presumably are.. and should be even if you did not manually specify inline ).

It would be very nice if compilers, and the language, could evolve to point to where the inline keyword is as relevant as the register keyword is today.


[edited by - haro on July 8, 2003 1:26:10 AM]

Share this post


Link to post
Share on other sites
As another thought, readonly variables would almost definitely have to be restricted to primitives for the sake of efficiency, since accessing a readonly object would mean preventing access to the address of that object which would mean returning a copy of the entire object any time it was requested.

On the other hand, this is what I intend with readonly variables. They would be commonly used non-complex types, such as coordinate positions which will likely be represented as simple sets of real numbers long into the future.

[edited by - haro on July 8, 2003 1:20:00 AM]

Share this post


Link to post
Share on other sites
C++ isn''t about reading and writing, it''s about showing and hiding. Providing interfaces. That''s exactly what encapsulation is. I''m sorry that you don''t like the way things are done now, but that''s the paradigm.

Share this post


Link to post
Share on other sites
quote:
Original post by Zipster
C++ isn't about reading and writing, it's about showing and hiding. Providing interfaces. That's exactly what encapsulation is. I'm sorry that you don't like the way things are done now, but that's the paradigm.


Actually, C++ is a language. OO is the paradigm. Paradigms are things of whim and OO could be obsolete next year, though highly unlikely.. but who would have thought purely C style procedural code would become veritably obsolete a few decades after it was accepted as the method for code development.

If you have anything negative to argue with the concept of readonly/writeonly themselves I'd love to hear, but comments such as: "Well, OO doesn't do it that way.. so its dumb." are pointless, ignorant and lead to a lack of creative thought, so shouldn't have been stated in the first place. Remember, paradigms aren't there for you to memorize and accept as "The one and only holy path of good coders." , but rather as guides and tools for development. If something goes completely against your paradigm(s) of choice but helps you complete your task in a more timely or efficient manner without consequence, then by all means follow through with it.

[edited by - haro on July 8, 2003 1:40:03 AM]

Share this post


Link to post
Share on other sites
readonly once existed. It was what const was originally called

But yes, readonly would be a neat feature. I''ve always hated using interfaces for the same purposes. It would be good if there was some distinction between accessing a variable to read it or to write to it.

Share this post


Link to post
Share on other sites
Fine then. I don''t have time to argue with you about languages and paradigms.

quote:
If you have anything negative to argue with the concept of readonly/writeonly themselves I''d love to hear

How do your new keywords eliminate the usage of those "pointless" 1-3 accessor functions? If a variable is readonly, then what happens when it needs to be written to? If a variable is writeonly, then what happens when it needs to be read? And if a variable is then both readonly and writeonly, then why isn''t it just private? Have you really thought out the usage of these keywords, or was it simply out of frustrating at all the accessor functions you had to write?

Share this post


Link to post
Share on other sites
quote:
Original post by Zipster
How do your new keywords eliminate the usage of those "pointless" 1-3 accessor functions? If a variable is readonly, then what happens when it needs to be written to? If a variable is writeonly, then what happens when it needs to be read? And if a variable is then both readonly and writeonly, then why isn't it just private? Have you really thought out the usage of these keywords, or was it simply out of frustrating at all the accessor functions you had to write?


I'm sorry, I hadn't realized you don't understand the basic concepts. Okay, let's say you create a new class, a particle class. And that particle class has a series of 3 variables representing the location of the individual particle (x,y,z). Now let's assume you want to access the x location of that particle for some function.

There are two ways to do that. Create an inlined function and make a call along the lines of:

someFunction( particle.GetXValue() );

Or as suggested, you could simply do:

someFunction( particle.x );

The latter method is cleaner and does not require dirty looking inlining to prevent having an extra 6 cycles added to a likely 2 cycle function. Now, the point of readOnly is that you are allowing classes outside of the particle class to read the data, but not to modify it. Do you understand at all?

particle.x = 13 would create a compile time error.

Let me know if you're still confused. writeonly is very similiar, only outside classes can only 'write' to the respective variables.. hence the name 'writeonly'.

EDIT: As far as a writeonly and readonly primitive, that would be illogical. That would be along the same lines as trying to declare an unsigned signed integer. And again, I would ask you to lay off the childish flames -- I'm not sure if you're truly as confused as you sound or if you're just trying to hijack the thread, either way I will not respond to further 'taunts' which these clearly are considering you wrote this message and then deleted it earlier for whatever reason.

[edited by - haro on July 8, 2003 2:31:36 AM]

Share this post


Link to post
Share on other sites
I brought up valid points. I understand the concept of your keywords, and now I''m challenging them because I don''t believe them substantial. I''m neither taunting you nor flaming you, just bringing up points I think need to be addressed. I''ll apologize about that last part, if that''s what''s upsetting you.

Let me start over. What happens if you have a variable that''s readonly, yet you want to write to it? With your keyword, only the class itself has permission to write to it. But how can the class always know when it needs to update the variable?

Let''s take your particle example. Right now, "outsiders" (let''s call them) can only read the position of the particle. Now, let''s say that I created a new wind class. I initialize this wind so that it is affecting the particle. The particle has to move, it''s being blown. But how is the particle supposed to know it''s being blown? One solution is to create a Blow() function or similar within the particle class, and call that while passing data so the particle can adjust it''s own attributes. Sounds great. Ok, right now the only force affecting the particle is wind, but let''s take this a bit further. Supposed we implemented ourselves an entire physics engine. In addition to wind, there are other forces, other particles, different types of movements and dynamics, friction, etc. If the particle is the only object that can alter it''s attributes, then we''d have to implement a function or method within the particle class itself for every possible interaction it can have with other objects, because other objects don''t have write access. At all. Let''s take this even further. Suppose every object in this physics engine was the same way (it''s the only one that can modify it''s attributes). Then each object has to know how it can interact with every other object, in addition to knowing how all other objects interact with it, and all your classes become bloated with methods pertaining to how other objects can modify them, while not actually giving the other classes this access.

On the other hand, you expose a SetX/Y/Z interface for the particle. Now the particle lets other objects alter it''s attributes, instead of being forced to know itself. This sounds like a nice solution. Now the particle can only be concerned with particle matters. If it''s being blown by wind, then pass it to the wind class and let the latter take control of it.

Now let''s consider writeonly. Seriously now, when''s the last time you had a variable you only needed write access to, and never needed to read? Often, you need to perform some sort of conditional check on the variable to determine it''s next value, or in the very least use the last value to determine the new one. In the case of the particle, the wind needs to know the particles current position so it knows how to update it. It can''t just write blindly. One solution is to write a DisplaceX function that only tells the particle how much to change X, and it can do it itself. But that''s in lieu of a GetX interface, which would probably be more useful in the long run.

My point is that you can''t completely get rid of the accessors. You may get rid of the SetX and GetX functions themselves, but you''re still stuck implementing some other function that allows outside objects to have an influence on internal attributes. At most, you might be able to eliminate half the accessors (Get for all readonly, Set for all writeonly), but either your net function count stays the same because you have to add other communicative functions, or you really only need one-way communication with your data. But all things considered, is that really worth new keywords? Especially considering the potentially limited usage of writeonly.

And lastly, I deleted my earlier message because I didn''t feel I was getting the point I wanted across that well. However, as you know I rewrote it, and in a form I personally felt was more effective. If I wanted to flame you, I would have done so already, but that''s not what I''m here to do, so I won''t. Although a good debate it always in my schedule

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Come on... this is pointless... besides you can always inline you functions and functions declared in the class definition are always inlined.

Share this post


Link to post
Share on other sites
You could always do something like this:


class Test
{
private:
double _variable;

public:
const double& variable;

Test (void);
}

Test::Test (void) : variable(_variable) {}


This way _variable is read/write accesible from within your class while variable is readonly from the outside (and inside), and will always have the same value as _variable.

edit: tags

[edited by - Wildfire on July 8, 2003 3:54:49 AM]

Share this post


Link to post
Share on other sites
What happens when the implementation of a class with a readonly or writeonly public variable change and that change affects the variable? It could be that suddenly you need a sanity check for a writeonly variable value or a readonly variable change to a pointer to the readonly value or something else. Now all your clients need to make the appropriate changes to about 10 000 places in their 4 billion lines long source code. To say that they would hate you is probably to make an understatement.

If you instead used a function from the start you could change the implementation how much you want without you clients need to change one line of there source code. That’s the beauty of C++ and therefore there is absolutely no reason whatsoever to include readonly or writeonly keywords.

Share this post


Link to post
Share on other sites
quote:
Original post by mputters
__declspec property



that is nothing but proprietary syntaxic sugar, to cover up the fact that you use get/set ''s. ( and will only compile in MSVC++ )



/Please excuse my bad spelling - My native language is binary not english
|Visit me
\Take my advice - I don''''t use it...

Share this post


Link to post
Share on other sites
That''s true. My above example only works if you never rename the variable, and if you don''t need to do something else anytime the variable is accessed. So you''d have to be 100% sure it will never change and will never require a function to be exectued on access.
So, it''s pretty much a theoretical example. If you ever decide to use it, be prepared for trouble

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
Fortunately Python has properties. You can let others access your variables freely, but when you need to add some extra processing to getters/setters, it''s easy.

class A:
def __init__(self):
self.x = 2

a = A()
a.x = 3

# Then the modified class
class B:
def __init__(self):
self.x = 2

def getX(self): return self.__x
def setX(self, x): print ''wazoo''; self.__x = x
x = property(getX, setX)

b = B()
b.x = 3 # also prints ''wazoo''

No more get/set hell. C++ could have the same too..

Share this post


Link to post
Share on other sites
If you want to know why, read "The Design and Evolution of C++" by Bjarne Stroustrup. It will tell you if they were rejected, or just not considered.

Furthermore, some proposals going in that direction (properties, delegation) are under consideration by the C++ Standard Committee. Check the publicly available papers on their website.

- Properties, Methods and Events
- Aspects of Forwarding (was C++ Support for Delegation)

If you feel so strongly about the topic, submit your own proposal. However, I would suggest you thoroughly study the archives of the comp.std.c++ newsgroup (Google archive link) before you do so.


[ Start Here ! | How To Ask Smart Questions | Recommended C++ Books | C++ FAQ Lite | Function Ptrs | CppTips Archive ]
[ Header Files | File Format Docs | LNK2001 | C++ STL Doc | STLPort | Free C++ IDE | Boost C++ Lib | MSVC6 Lib Fixes ]


[edited by - Fruny on July 8, 2003 5:54:24 AM]

Share this post


Link to post
Share on other sites
quote:
Original post by haro
As the example program shows, if the readonly variable was changed to a const then the program would not compile since the update function CHANGES THE VALUE OF THE READONLY VARIABLE SINCE IT IS WITHIN THE SAME CLASS AS THE VARIABLE WAS DECLARED WITHIN.


NO NEED TO SHOUT! Ever heard of const_cast? Anyway, there is nothing wrong with accessor fns (as mentioned by just about everyone else in this thread)

Share this post


Link to post
Share on other sites
quote:
Original post by haro
As another thought, readonly variables would almost definitely have to be restricted to primitives for the sake of efficiency, since accessing a readonly object would mean preventing access to the address of that object which would mean returning a copy of the entire object any time it was requested.
[edited by - haro on July 8, 2003 1:20:00 AM]


No only the compiler would have to worry about readonly and writeonly, once the code is compiled, the code doesn''t check if an address is readonly or writeonly (why would it ? The compiler has allready made sure that the code doesn''t violate writeonly and readonly).

Share this post


Link to post
Share on other sites
Guest Anonymous Poster
quote:
Original post by dagarach
Anyway, there is nothing wrong with accessor fns (as mentioned by just about everyone else in this thread)
Yes there is. They have to be implemented even if the do nothing special (get-methods rarely do) and you need to type more when accessing. I''d rather be more concise.

Share this post


Link to post
Share on other sites
quote:
Original post by haro
Why was the concept of readonly/writeonly variables not included in C++? The idea is simple and useful. A readonly variable can only be written to by the class it is created within. A writeonly variable can only be read from the class it is created within.

Personally, I don't like em. I find:

Unit.SetWaypoint( destination );

easier to read than:

Unit.waypoint = destination;

and the former can easily change the 'waypoint' variable to a list and add the function:

Unit.AppendWaypoint( destination );

whereas trying to do the same thing in the latter would break your code.

quote:

This style would allow for easy and efficient C style data access since there is no function call overhead using C++ style data accessor functions. But at the same time you would maintain the safety and encapsulation C++ offers. Its win win.



inline it. If your compiler isn't dumb it will pay heed to such notices, and will inline it even without you asking. If your compiler is dumb, it has enough problems to deal with, without trying to add support for even more keywords.

And thus there won't be any overhead.

I've allready given an example of a way such variables are inheritly unsafe.

quote:

Writeonly variables would be similiar, only they would not be able to be read from. While likely not as useful as readonly, writeonly would definitely still have use. Namely in setting state variables of an object before updating that object and insuring proper adherence to the interface.



And then how is this updating supposed to know which state variables have random garbage, and which ones have newly entered data? I think this would be easier to find out if functions were used. This happens to apply to normal public variables anyways. Making them 'write only' will not solve the problem.

quote:

There would be no reason to read variables which should be obsolete before updating the object,



And thus no reason to need to protect the programmer from something he won't do.

quote:

...and with writeonly variables the object could insure this is an effective fashion without having to rely on potentially costly function overhead if the only ways to modify its state data was with tiny manipulator functions.



*sigh* you don't need to insure what is allready insured, unless you have a dumb programmer, in which case you're allready pretty screwed. Plus, after it has been updated, you'll end up having to write accessor functions to let them read the variable. You say: "then you could just make it a normal variable again".

I say: Then you're letting the programmer read it even when it might be undefined. Oh, and since you now have to change to using functions, now you also have to create a specialized class with overloaded functions to prevent code breakage.

quote:

This seems much more elegant and in the C++ spirit, rather than writing the 1-3 line functions and relying on the virtually undefined implementation of inline and the obfuscation its obscurities bring your code.


I hardly think that the C++ spirit, which would be the OO padigram you talk about in later posts, involves removing the ability to encapsulate your data. Also, last I checked, if a function is larger than 1 line, it's probably doing something besides just returning the variable, or setting it, as both can be done in one line. Thus, you either mean 1 line functions, or you found a way of fusing function calls into read/writes to variables.

And personally, which reads easier?

Unit.SetNextWaypoint( new_waypoint );

or

resize_array( Unit.destination , ++Unit.last_destination );
Unit.destination[Unit.last_destination] = new_waypoint;

?

Or how about:

class Unit
{
public:
int last_destination;
waypoint *destination; //array
void Update( void );
};

or:

class Unit
{
public:
void SetWaypoint( waypoint *to );
void AddWaypoint( waypoint *next );
void Update( void );
private:
//...stuff you dont need to even look at...
};

?

I happen to think the latter is much easier to read in both cases. And functions, unlike variables, can be overloaded to provide new interfaces with multiple variable inputs if needed, while not breaking your old code.

quote:
Original post by George2

Original post by haro
As another thought, readonly variables would almost definitely have to be restricted to primitives for the sake of efficiency, since accessing a readonly object would mean preventing access to the address of that object which would mean returning a copy of the entire object any time it was requested.
[edited by - haro on July 8, 2003 1:20:00 AM]

No only the compiler would have to worry about readonly and writeonly, once the code is compiled, the code doesn't check if an address is readonly or writeonly (why would it ? The compiler has allready made sure that the code doesn't violate writeonly and readonly).


What happens if you happen to get a pointer to the variable?
Trying to insure that every possible way to reference a write/read only dosn't get abused sure sounds like a whole lot more extra code for compilers, taking away time that could be spent on optimization routines...

[edited by - MaulingMonkey on July 8, 2003 7:34:48 AM]

Share this post


Link to post
Share on other sites
I know __declspec property is compiler specific, but it happens to be what the original poster wanted (accessing a variable directly with its name) while keeping the encapsulation. I personally wouldn''t use it, but it was just to provide information...

Share this post


Link to post
Share on other sites
Accessor functions are about more than just preventing reading or writing of variables. They are about keeping the interface constant even when the implementation changes. Sometimes you might want to completely remove a readonly variable and just calculate it on demand from other values. An accessor function lets you do that without changing the interface, your idea wouldn''t. It''s often useful to be able to do something when one of your variables is changed by an external class - perhaps a lazy update of other internal values that depend on the changed value. Again this is easy to do with an accessor function without changing the interface but not with your idea. I don''t know Python but it looks like the property idea mentioned earlier gives you the best of both worlds.

Someone else recommended ''The Design and Evolution of C++'' and it''s definitely worth a read to understand why the design decisions in C++ were made the way they were. One point Stroustroup continually emphasises is that he was very reluctant to add new keywords that did not add new functionality but only added ''syntactic sugar'' - a more concise or neater way of expressing something you could already express using existing language features. Your idea would be rejected on that basis. Introducing new keywords will invariably break some existing code that uses those words as variable, class or function names so is not something to be done lightly.

Share this post


Link to post
Share on other sites