Attribute presence generic check - c++

My requirement is to parse on XML and populate an object. How do I automatically track if attribute xyz is present once the object is populated from the Xml. Please note that I will no longer have access to the parsed buffer after the object is populated. Hence I need some mechanism to know whether the attribute was present in XML and the same is populated in the object.
I have the below solution in my mind but not sure if anything more efficient possible. Also I am looking for a generic solution for this problem.
define a bit for each of the attribute in a class.
setter function should set that bit while parsing XML when attribute is present
getter function should check the bit before returning the attribute value by reference argument . It should return false when bit is not set. ( The getter function return type should be boolean and it accepts one argument which is of type attribute and populate it when present)

From your comment I gather that you can change the design, so this is what I would do:
Replace all optional members with the aptly-named std::optional or the boost equivalent if the former is not available.
using std::optional; // facilitates easy switching between std and boost if needed
class MyClass {
optional<int> some_value;
// Similarly for rest of attributes
void set_some_value(int value_to_store) { some_value = value_to_store; }
optional<int> get_some_value() { return some_value; }
}
To read from it do as follows
MyClass instance;
// ... parse XML and set attributes
auto some_value = instance.get_some_value;
if (some_value) {
do_something_with_int(*some_value);
}
Some notes on optional:
Default-constructed optionals are empty. This means that every attribute you don't explicitly set is empty by default.
Dereferencing an empty optional is undefined behavior. There are safer ways to access it. In this example it is safe because we manually checked for it since I assume you'd like to branch on the existence of your attribute anyway.
The managed object is guaranteed to be inside the allocated optional object. This means no dynamic allocation which is great for speed. If you have any huge objects, however, this can cause stack overflow issues. It's not likely, though, as most real world scenarios of large objects are using a string or some STL container/wrapper that holds its data on the heap anyway.
I couldn't find a mention of the space cost in the standard. I believe it is typically implemented with a single bool inside every optional object. sizeof(bool) is often sizeof(int). This makes it more space consuming than necessary, but it's as fast as possible. This is generally a good trade-off, but if you encounter memory usage problems and you have a lot of objects holding optionals you might need to find a more space-optimal solution. If you can use sentinel values to signal non-existence, look up implementations of compact optional objects.

Related

What's the advantage of `std::optional` over `std::shared_ptr` and `std::unique_ptr`?

The reasoning of std::optional is made by saying that it may or may not contain a value. Hence, it saves us the effort of constructing a, probably, big object, if we don't need it.
For example, a factory here, will not construt the object if some condition is not met:
#include <string>
#include <iostream>
#include <optional>
std::optional<std::string> create(bool b)
{
if(b)
return "Godzilla"; //string is constructed
else
return {}; //no construction of the string required
}
But then how is this different from this:
std::shared_ptr<std::string> create(bool b)
{
if(b)
return std::make_shared<std::string>("Godzilla"); //string is constructed
else
return nullptr; //no construction of the string required
}
What is it that we win by adding std::optional over just using std::shared_ptr in general?
What is it that we win by adding std::optional over just using std::shared_ptr in general?
Let's say you need to return a symbol from a function with flag "not a value". If you would use std::shared_ptr for that you would have huge overhead - char would be allocated in dynamic memory, plus std::shared_ptr would maintain control block. While std::optional on another side:
If an optional contains a value, the value is guaranteed to be
allocated as part of the optional object footprint, i.e. no dynamic
memory allocation ever takes place. Thus, an optional object models an
object, not a pointer, even though the operator*() and operator->()
are defined.
so no dynamic memory allocation is involved and difference comparing even to the raw pointer could be significant.
An optional is a nullable value type.
A shared_ptr is a reference counted reference type that is nullable.
A unique_ptr is a move-only reference type that is nullable.
What they share in common is that they are nullable -- that they can be "absent".
They are different, in that two are reference types, and the other is a value type.
A value type has a few advantages. First of all, it doesn't require allocation on the heap -- it can be stored along side other data. This removes a possible source of exceptions (memory allocation failure), can be much faster (heaps are slower than stacks), and is more cache friendly (as heaps tend to be relatively randomly arranged).
Reference types have other advantages. Moving a reference type does not require that the source data be moved.
For non-move only reference types, you can have more than one reference to the same data by different names. Two different value types with different names always refer to different data. This can be an advantage or disadvantage either way; but it does make reasoning about a value type much easier.
Reasoning about shared_ptr is extremely hard. Unless a very strict set of controls is placed on how it is used, it becomes next to impossible to know what the lifetime of the data is. Reasoning about unique_ptr is much easier, as you just have to track where it is moved around. Reasoning about optional's lifetime is trivial (well, as trivial as what you embedded it in).
The optional interface has been augmented with a few monadic like methods (like .value_or), but those methods often could easily be added to any nullable type. Still, at present, they are there for optional and not for shared_ptr or unique_ptr.
Another large benefit for optional is that it is extremely clear you expect it to be nullable sometimes. There is a bad habit in C++ to presume that pointers and smart pointers are not null, because they are used for reasons other than being nullable.
So code assumes some shared or unique ptr is never null. And it works, usually.
In comparison, if you have an optional, the only reason you have it is because there is the possibility it is actually null.
In practice, I'm leery of taking a unique_ptr<enum_flags> = nullptr as an argument, where I want to say "these flags are optional", because forcing a heap allocation on the caller seems rude. But an optional<enum_flags> doesn't force this on the caller. The very cheapness of optional makes me willing to use it in many situations I'd find some other work around if the only nullable type I had was a smart pointer.
This removes much of the temptation for "flag values", like int rows=-1;. optional<int> rows; has clearer meaning, and in debug will tell me when I'm using the rows without checking for the "empty" state.
Functions that can reasonably fail or not return anything of interest can avoid flag values or heap allocation, and return optional<R>. As an example, suppose I have an abandonable thread pool (say, a thread pool that stops processing when the user shuts down the application).
I could return std::future<R> from the "queue task" function and use exceptions to indicate the thread pool was abandoned. But that means that all use of the thread pool has to be audited for "come from" exception code flow.
Instead, I could return std::future<optional<R>>, and give the hint to the user that they have to deal with "what happens if the process never happened" in their logic.
"Come from" exceptions can still occur, but they are now exceptional, not part of standard shutdown procedures.
In some of these cases, expected<T,E> will be a better solution once it is in the standard.
A pointer may or may not be NULL. Whether that means something to you is entirely up to you. In some scenarios, nullptr is a valid value that you deal with, and in others it can be used as a flag to indicate "no value, move along".
With std::optional, there is an explicit definition of "contains a value" and "doesn't contain a value". You could even use a pointer type with optional!
Here's a contrived example:
I have a class named Person, and I want to lazily-load their data from the disk. I need to indicate whether some data has been loaded or not. Let's use a pointer for that:
class Person
{
mutable std::unique_ptr<std::string> name;
size_t uuid;
public:
Person(size_t _uuid) : uuid(_uuid){}
std::string GetName() const
{
if (!name)
name = PersonLoader::LoadName(uuid); // magic PersonLoader class knows how to read this person's name from disk
if (!name)
return "";
return *name;
}
};
Great, I can use the nullptr value to tell whether the name has been loaded from disk yet.
But what if a field is optional? That is, PersonLoader::LoadName() may return nullptr for this person. Do we really want to go out to disk every time someone requests this name?
Enter std::optional. Now we can track if we've already tried to load the name and if that name is empty. Without std::optional, a solution to this would be to create a boolean isLoaded for the name, and indeed every optional field. (What if we "just encapsulated the flag into a struct"? Well, then you'd have implemented optional, but done a worse job of it):
class Person
{
mutable std::optional<std::unique_ptr<std::string>> name;
size_t uuid;
public:
Person(size_t _uuid) : uuid(_uuid){}
std::string GetName() const
{
if (!name){ // need to load name from disk
name = PersonLoader::LoadName(uuid);
}
// else name's already been loaded, retrieve cached value
if (!name.value())
return "";
return *name.value();
}
};
Now we don't need to go out to disk each time; std::optional allows us to check for that. I've written a small example in the comments demonstrating this concept on a smaller scale
Importantly, you get a known, catchable, exception instead of undefined behaviour if you try to access the value() from an optional when it's not there. Thus, if things go wrong with an optional you're likely to have a much better time debugging than if you were to use shared_ptr or the like. (Note that the * dereference operator on an optional still gives UB in this case; using value() is the safer alternative).
Also, there's the general convenience of methods such as value_or, which allow you to specify a "default" value quite easily. Compare:
(t == nullptr) ? "default" : *t
with
t.value_or("default")
The latter is both more readable and slightly shorter.
Finally, the storage for an item in an optional is within the object. This means that an optional requires more storage that a pointer if the object is not present; however, it also means that no dynamic allocation is required to put an object into an empty optional.
What is it that we win by adding std::optional over just using std::shared_ptr in general?
#Slava mentioned the advantage of performing no memory allocations, but that's a fringe benefit (OK, it may be a significant benefit in some cases, but my point is, it is not the main one).
The main benefit is (IMHO) clearer semantics:
Returning a pointer usually means (in modern C++) "allocates memory", or "handles memory", or "knows the address in memory of this and that".
Returning an optional value means "not having a result of this computation, is not an error": the name of the return type, tells you something about how the API was conceived (the intent of API, instead of implementation).
Ideally, if your API doesn't allocate memory, it shouldn't return a pointer.
Having optional type available in the standard, ensures you can write more expressive APIs.

C++: What is recommended way to distinguish between string which never had the value set and empty string?

We have a Java messaging API which we are translating to C++. The messages typically have simple data types, like string, int, double, etc. When a message is constructed, we initialize all the member variables to a default value which the API recognizes as a "null" value (i.e. never set to any value), e.g. Integer.MAX_VALUE for int types. Any fields which are considered null are not serialized and sent.
In Java, strings automatically initialize to null so it's easy to differentiate between a string field which is null versus a string which is empty string (which is a legal value to send in the message).
I'm not sure of the best way to handle this in C++, since the strings automatically initialize to an empty string, and empty string is a legal value to send over the API. We could default strings to some control character (which would not be a legal value in our API), but I'm wondering if there is a more conventional or better way to do this.
We're all new here to C++, so we may have overlooked some obvious approach.
The recommended way is to make is that the object doesn't exist until it has a valid value. If a message wit a null string isn't valid, why allow it?
You can't avoid it in Java, because a string can always be null.
But C++ gives you the tool to create a class which is guaranteed to always hold a string.
And it sounds like that's what you want.
For what you're asking for, the best approach is really to build into the class the invariant that objects of this class always have a string set. Instead of setting all the objects to some default value in the constructor, define the constructor to take the actual parameters and set the members to valid values.
However, if you want to specify an "optional" value, there are a couple of broad approaches:
either use a pointer (preferably a smart pointer). A pointer to a string can be null, or it can point to a valid string (which, again, may or may not be empty)
alternatively, use something like boost::optional from the Boost libraries. This is a clever little utility template which lets you define, well, optional values (the object may contain a string, or it may be null)
or you could simply add a bool flag (something like has_string, which, when not set, indicates that no string has been set, and the string value should be disregarded).
Personally, I'd prefer the last two approaches, but all three are fairly commonly used, and will work just fine. But the best approach is the one in which you design the class so that the compiler can guarantee that it'll always be valid. If you don't want messages with a null string, let the compiler ensure that messages will never have a null string.
To replicate Java "things can have values, or lack values", probably the most general way is to store boost::optional<T>, or in the next version of the standard, std::optional<T>.
You do have to throw in some * and -> if you want to read their values, and be careful about optional<bool> because its default conversion to bool is "am I initialized or not?", not the bool that is stored. But operator= does pretty much what you want it to when writing to it, it is just reading from it that can do unexpected things in a bool context.
To tell if an optional<T> is initialized, just evaluate it in a bool context like you might a pointer. To extract its value after you have confirmed it is initialized, use the unary * operator.
boost is a relatively high quality library with a high rate of code migrating from it to the C++ standard in 5 to 10 years. It does contain some scary parts (like phoenix!), and in general you should make sure that whatever component you are using isn't already in the C++ standard library (having migrated there). boost::optional in particular is part of their header-only libraries, which are easier to use (as you don't have to build boost to use them).

class member is not attached c++

I read in data from an XML file, depending on the tags in the xml file, data gets attached to class member variables.
Is it possible if for example a value in the xml file contains "!", which in this case is not valid thus I can't accept that value.
So the member variable for that value is empty.
But the type of some member variables are other classes or integers or boolean. How can I check if those values are set? As there is no function emtpy() for those.
If they are not optional, you must cause your parsing mechanism to error when they are not present. Else, you could use something like boost::optional.
There is no way to detect at run time, whether a variable has been explicitly set. That's why some compilers give you a warning (not an error), if they suspect that a variable might be used uninitialized.
It is the programmer's responsibility, to keep track of what variables have been set. The low level way to do this, is to use pointers, initialize them to 0, change them when they should point to some initialized memory and change them back to 0 when the object they point to is deleted.
In C++, you can use Boost.Optional to spare you from messing around with pointers in this way.
you could during XML read, check the XML value and if it contains "!", assign a default value to whatever variable it is.
e.g. set ptr to nullptr, boolean to false and int to 0 or -1.
Use const default values whenever you can, that will make your code clearer and easier to maintain.

C++ Is using auto_ptr references as out variables idiomatic?

Suppose I want to write factory method that is supposed to allocate heterogeneous objects on the heap and return them to the caller. I am thinking of designing the API like this:
bool MakeEm(auto_ptr<Foo>& outFoo, auto_ptr<Bar>& outBar) {
...
if (...) {
return false;
}
outFoo.reset(new Foo(...));
outBar.reset(new Bar(...));
return true;
}
This allows a caller to do this:
auto_ptr<Foo> foo;
auto_ptr<Bar> bar;
MakeEm(foo, bar);
My question is: "Is this idiomatic? If not, what is the right way to do this?"
The alternative approaches I can think of include returning a struct of auto_ptrs, or writing the factory API to take raw pointer references. They both require writing more code, and the latter has other gotchyas when it comes to exception safety.
Asking of something is idiomatic can get you some very subjective answers.
In general, however, I think auto_ptr is a great way to convey ownership, so as a return from a class factory - it's probably a Good Thing.
I would want to refactor this, such that
You return one object instead of 2. If you need 2 objects that are so tightly coupled they cannot exist without each other I'd say you have a strong case for is-a or has-a refactoring.
This is C++. Really ask yourself if you should return a value indicating success, forcing the consumer of your factory to have to check every time. Throw exceptions or pass exceptions from the constructors of your classes in the factory. Would you ever want to be OK with false and try to operate on uninitialized auto_ptr's?
You don't have to make up your own struct to return two values - you can use std::pair. In that case there isn't much syntactic overhead in returning the two values. This solution does have the problem that ".first" and ".second" aren't very descriptive names, but if the types involved and the name of the function make the intent clear enough then that's not necessarily a problem.
If you are using C++0x you could use unique_ptr insted of auto_ptr and the caller can use auto instead of having to type the longer std::pair<std::unique_ptr<A>, std::unique_ptr<B>>. If you are not using C++0x you might consider using a typedef for that instead.
If you return the two values then you won't have space for the bool. You could use a C++0x tuple to return all three values. You could also indicate error by throwing an exception or by returning null pointers. I would prefer an exception assuming that the error is rare/exceptional.
As other answers have pointed out, it is often preferable to have two separate functions that each return a single object. If you can't do that because the initialization of the two objects is inextricably linked then you could make a class that encapsulates the initialization. You could pass the necessary information to make the two objects to the constructor (requires exception to signal errors) and then have two methods on that class that yield one object each.
Let's assume that a return value of false means "don't look at the output parameters".
Then what I would do is get rid of the bool return value, return a struct or pair that has the auto_pointers you want, and throw in the error condition.
Usually when you have auto_ptr parameters they are not references.
This is because when you pass something to a function that takes auto_ptr you are expecting that function to take ownership. If you are passing by reference it does not actually take the object (it may take the object).
Its a subtle point, but in the end you need to look at what your interface is trying to say to the user.
Also you seem to be using it as an out parameter.
Personally I have never seen this use case (but I can see it) just document what you are trying to do and more importantly why.
As a general rule, if it involves auto_ptr, it's not idiomatic. In general, the structure is not idiomatic too- normally, you'd make one function for each, return by value and throw an exception if they fail, and if you need to share variables, make it an object.

Is it a good (correct) way to encapsulate a collection?

class MyContainedClass {
};
class MyClass {
public:
MyContainedClass * getElement() {
// ...
std::list<MyContainedClass>::iterator it = ... // retrieve somehow
return &(*it);
}
// other methods
private:
std::list<MyContainedClass> m_contained;
};
Though msdn says std::list should not perform relocations of elements on deletion or insertion, is it a good and common way to return pointer to a list element?
PS: I know that I can use collection of pointers (and will have to delete elements in destructor), collection of shared pointers (which I don't like), etc.
I don't see the use of encapsulating this, but that may be just me. In any case, returning a reference instead of a pointer makes a lot more sense to me.
In a general sort of way, if your "contained class" is truly contained in your "MyClass", then MyClass should not be allowing outsiders to touch its private contents.
So, MyClass should be providing methods to manipulate the contained class objects, not returning pointers to them. So, for example, a method such as "increment the value of the umpteenth contained object", rather than "here is a pointer to the umpteenth contained object, do with it as you wish".
It depends...
It depends on how much encapsulated you want your class to be, and what you want to hide, or show.
The code I see seems ok for me. You're right about the fact the std::list's data and iterators won't be invalidated in case of another data/iterator's modification/deletion.
Now, returning the pointer would hide the fact you're using a std::list as an internal container, and would not let the user to navigate its list. Returning the iterator would let more freedom to navigate this list for the users of the class, but they would "know" they are accessing a STL container.
It's your choice, there, I guess.
Note that if it == std::list<>.end(), then you'll have a problem with this code, but I guess you already know that, and that this is not the subject of this discussion.
Still, there are alternative I summarize below:
Using const will help...
The fact you return a non-const pointer lets the user of you object silently modify any MyContainedClass he/she can get his/her hands on, without telling your object.
Instead or returning a pointer, you could return a const pointer (and suffix your method with const) to stop the user from modifying the data inside the list without using an accessor approved by you (a kind of setElement ?).
const MyContainedClass * getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return &(*it);
}
This will increase somewhat the encapsulation.
What about a reference?
If your method cannot fail (i.e. it always return a valid pointer), then you should consider returning the reference instead of the pointer. Something like:
const MyContainedClass & getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return *it;
}
This has nothing to do with encapsulation, though..
:-p
Using an iterator?
Why not return the iterator instead of the pointer? If for you, navigating the list up and down is ok, then the iterator would be better than the pointer, and is used mostly the same way.
Make the iterator a const_iterator if you want to avoid the user modifying the data.
std::list<MyContainedClass>::const_iterator getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return it;
}
The good side would be that the user would be able to navigate the list. The bad side is that the user would know it is a std::list, so...
Scott Meyers in his book Effective STL: 50 Specific Ways to Improve Your Use of the Standard Template Library says it's just not worth trying to encapsulate your containers since none of them are completely replaceable for another.
Think good and hard about what you really want MyClass for. I've noticed that some programmers write wrappers for their collections just as a matter of habit, regardless of whether they have any specific needs above and beyond those met by the standard STL collections. If that's your situation, then typedef std::list<MyContainedClass> MyClass and be done with it.
If you do have operations you intend to implement in MyClass, then the success of your encapsulation will depend more on the interface you provide for them than on how you provide access to the underlying list.
No offense meant, but... With the limited information you've provided, it smells like you're punting: exposing internal data because you can't figure out how to implement the operations your client code requires in MyClass... or possibly, because you don't even know yet what operations will be required by your client code. This is a classic problem with trying to write low-level code before the high-level code that requires it; you know what data you'll be working with, but haven't really nailed down exactly what you'll be doing with it yet, so you write a class structure that exposes the raw data all the way to the top. You'd do well to re-think your strategy here.
#cos:
Of course I'm encapsulating
MyContainedClass not just for the sake
of encapsulation. Let's take more
specific example:
Your example does little to allay my fear that you are writing your containers before you know what they'll be used for. Your example container wrapper - Document - has a total of three methods: NewParagraph(), DeleteParagraph(), and GetParagraph(), all of which operate on the contained collection (std::list), and all of which closely mirror operations that std::list provides "out of the box". Document encapsulates std::list in the sense that clients need not be aware of its use in the implementation... but realistically, it is little more than a facade - since you are providing clients raw pointers to the objects stored in the list, the client is still tied implicitly to the implementation.
If we put objects (not pointers) to
container they will be destroyed
automatically (which is good).
Good or bad depends on the needs of your system. What this implementation means is simple: the document owns the Paragraphs, and when a Paragraph is removed from the document any pointers to it immediately become invalid. Which means you must be very careful when implementing something like:
other objects than use collections of
paragraphs, but don't own them.
Now you have a problem. Your object, ParagraphSelectionDialog, has a list of pointers to Paragraph objects owned by the Document. If you are not careful to coordinate these two objects, the Document - or another client by way of the Document - could invalidate some or all of the pointers held by an instance of ParagraphSelectionDialog! There's no easy way to catch this - a pointer to a valid Paragraph looks the same as a pointer to a deallocated Paragraph, and may even end up pointing to a valid - but different - Paragraph instance! Since clients are allowed, and even expected, to retain and dereference these pointers, the Document loses control over them as soon as they are returned from a public method, even while it retains ownership of the Paragraph objects.
This... is bad. You've end up with an incomplete, superficial, encapsulation, a leaky abstraction, and in some ways it is worse than having no abstraction at all. Because you hide the implementation, your clients have no idea of the lifetime of the objects pointed to by your interface. You would probably get lucky most of the time, since most std::list operations do not invalidate references to items they don't modify. And all would be well... until the wrong Paragraph gets deleted, and you find yourself stuck with the task of tracing through the callstack looking for the client that kept that pointer around a little bit too long.
The fix is simple enough: return values or objects that can be stored for as long as they need to be, and verified prior to use. That could be something as simple as an ordinal or ID value that must be passed to the Document in exchange for a usable reference, or as complex as a reference-counted smart pointer or weak pointer... it really depends on the specific needs of your clients. Spec out the client code first, then write your Document to serve.
The Easy way
#cos, For the example you have shown, i would say the easiest way to create this system in C++ would be to not trouble with the reference counting. All you have to do would be to make sure that the program flow first destroys the objects (views) which holds the direct references to the objects (paragraphs) in the collection, before the root Document get destroyed.
The Tough Way
However if you still want to control the lifetimes by reference tracking, you might have to hold references deeper into the hierarchy such that Paragraph objects holds reverse references to the root Document object such that, only when the last paragraph object gets destroyed will the Document object get destructed.
Additionally the paragraph references when used inside the Views class and when passed to other classes, would also have to passed around as reference counted interfaces.
Toughness
This is too much overhead, compared to the simple scheme i listed in the beginning. It avoids all kinds of object counting overheads and more importantly someone who inherits your program does not get trapped in the reference dependency threads traps that criss cross your system.
Alternative Platforms
This kind-of tooling might be easier to perform in a platform that supports and promotes this style of programming like .NET or Java.
You still have to worry about memory
Even with a platform such as this you would still have to ensure your objects get de-referenced in a proper manner. Else outstanding references could eat up your memory in the blink of an eye. So you see, reference counting is not the panacea to good programming practices, though it helps avoid lots of error checks and cleanups, which when applied the whole system considerably eases the programmers task.
Recommendation
That said, coming back to your original question which gave raise to all the reference counting doubts - Is it ok to expose your objects directly from the collection?
Programs cannot exist where all classes / all parts of the program are truly interdependent of each other. No, that would be impossible, as a program is the running manifestation of how your classes / modules interact. The ideal design can only minimize the dependencies and not remove them totally.
So my opinion would be, yes it is not a bad practice to expose the references to the objects from your collection, to other objects that need to work with them, provided you do this in a sane manner
Ensure that only a few classes / parts of your program can get such references to ensure minimum interdependency.
Ensure that the references / pointers passed are interfaces and not concrete objects so that the interdependency is avoided between concrete classes.
Ensure that the references are not further passed along deeper into the program.
Ensure that the program logic takes care of destroying the dependent objects, before cleaning up the actual objects that satisfy those references.
I think the bigger problem is that you're hiding the type of collection so even if you use a collection that doesn't move elements you may change your mind in the future. Externally that's not visible so I'd say it's not a good idea to do this.
std::list will not invalidate any iterators, pointers or references when you add or remove things from the list (apart from any that point the item being removed, obviously), so using a list in this way isn't going to break.
As others have pointed out, you may want not want to be handing out direct access to the private bits of this class. So changing the function to:
const MyContainedClass * getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return &(*it);
}
may be better, or if you always return a valid MyContainedClass object then you could use
const MyContainedClass& getElement() const {
// ...
std::list<MyContainedClass>::const_iterator it = ... // retrieve somehow
return *it;
}
to avoid the calling code having to cope with NULL pointers.
STL will be more familiar to a future programmer than your custom encapsulation, so you should avoid doing this if you can. There will be edge cases that you havent thought about which will come up later in the app's lifetime, wheras STL is failry well reviewed and documented.
Additionally most containers support somewhat similar operations like begin end push etc. So it should be fairly trivial to change the container type in your code should you change the container. eg vector to deque or map to hash_map etc.
Assuming you still want to do this for a more deeper reason, i would say the correct way to do this is to implement all the methods and iterator classes that list implements. Forward the calls to the member list calls when you need no changes. Modify and forward or do some custom actions where you need to do something special (the reason why you decide to this in the first place)
It would be easier if STl classes where designed to be inherited from but for efficiency sake it was decided not to do so. Google for "inherit from STL classes" for more thoughts on this.