@Fuz:I've discussed this issue with several folks on the committee in the past, the consensus is that it is guaranteed because it isn't explicitly disallowed. From Howard Hinnant:
Yes, it is allowed and guaranteed to give the expected answer. There's not a particular place I can quote. The general reasoning is that nowhere in the standard does it say it is disallowed. Compare that with Table 100:
a.insert(p, i, j)
pre: i and j are not iterators into a. Inserts copies of elements in [i, j) before p
It is pretty easy for implementations to guarantee this behavior:
In the has-capacity-case it is very easy to see there is no problem.
In the doesn't-have-capacity-case, the new buffer must be created and filled and all the implementation has to do is to make sure the new value is constructed prior to deleting the old buffer.
vector.insert(p, v[i]) is more interesting to implement, but is also guaranteed to work.
@Will:From how the current wording is phrased, I believe it is still an issue. The problem is the use of the term move assignment operator in the added section of 12.8.20 instead of using is_move_assignable. I have not been following the issue with the committee and do not know if there is an objection to changing the wording to be concept based.
@MarkusWerle:Much the same way - but I build the lookup table as just a static table harvested from the code sorted by the type name. Another approach I've used for messages is to defer deserialization until code extracts the value (at which point the class being extracted is known). It avoids the global registry but requires that the code extracting has full information about the type.
The global registry problem is a classic "there is no good way to do that in C++" problem.
@sutm: The answer given by @bkuhns: stack overflow is correct. I would phrase it a bit differently. The axioms of copy are that copies are equal and modifying the copy does not modify the original. By convention, a const value is not modified in any apparent way (though there are many ways that const can be circumvented, doing so violates convention). So as long as a const reference to a value has a lifetime at least as long a the reference, a const reference has value semantics.
This is why we are able to pass argument by const& to avoid a copy. The caller guarantees, by convention, that the value is not modified and will survive for the duration of the call. With a shared_ptr, the lifetime of the object is ensured by the ref-counted pointer.
There is a subtle difference with equality - comparing share_ptr for equality, with respect to the shared object, is comparing identity. This doesn't violate the axioms of copy - copies are equal because they are identical, but is typically not the desired comparison. But since we don't expose the "raw" shared_ptr from our object_t, we can trivially provide an equality operator on object_t which returns true iff the contained objects are equal.
Element of Programming (EoP) has a great discussion on the topics of copy and equality and precisely defines the semantics of both operations. You might also look at this paper:
When the instance of my_class_t is placed into the document, an object_t is constructed through the template constructor.
The constructor instantiates an instance of model<my_class_t>
The instance of model<my_class_t> has a virtual draw method, that forwards to the draw function taking a my_class_t instance
The object_t is not a templated type, but holds a pointer to a concept_t - from which the model<> is derived. The technique is known as "type-erasure" and is used by std::function<>, boost::any, and other libraries.
So long as there is a stand alone draw function (or the class is serializable through stream out - so it picks up the default implementation of draw), then it can be stored in an object_t, and into the document. No (client-side) inheritance required.
Answer 1: For best performance pass by universal reference or supply all permutations of r-value/l-value. But profile first - it usually will do no better than pass by value and may end up slower since you have more code polluting your icache. Either approach adds size and complexity to your code - you might be better off investing in other optimizations.
Answer 2: Use std::stable_sort() to obey the previous ordering(s). For example, let's say the user clicked on the "state" column - you would sort by state as:
@tomkirbygreen:I don't have a "coding guidelines" document in text form. The work from STLab can be found at stlab.adobe.com where you can find the ASL libraries. There are also docs, papers, and presentations on the wiki: stlab.adobe.com/wiki. I also can't recommend working your way through "Elements of Programming" enough.
The STLab has been gone for a few years now - and ASL has been decaying a bit. I'm trying to get development moved over to github, and you can find the latest code here github.com/stlab/legacy (the reason it is in a "legacy" repo is that the plan is to clean it up and break it into seperate libraries that will go into the adobe-source-libraries repo and/or get submitted to boost).
I'm also looking for a decent blog space to make some of my coding tips public - github pages hasn't been worked for me in my attempts to get that going.
Then wrap will not get a default move assignment. For wrap to get a default noexcept move assignment, all members must have a noexcept move assignment - this determination is made by signature. That is the standard says that for wrap to get a default noexcept move assignment all members must have a move assignment with the signature T& operator=(T&&) noexcept.
The fix is to rephrase the requirement so it says that a struct or class will get a default noexcept move assignment if all members satisfies is_nothrow_move_assignable<T> - which the above does. That is, we want to define the requirement in terms of the concept, or operation semantics, and not in terms of matching an exact signature.