Is it safe to use a SortedSet <String>?


#1

As per subject, I am particularly worried by the following statement in SortedSet doc:

if you’re using a class or struct as the element type, it must be capable of being copied or moved with a straightforward memcpy, rather than needing construction and destruction code

I don’t know whether String meets that requirement and, more important, if it is part of the specification that it will always be so.


#2

Yep, that’ll work fine.


#3

So the constraint is std::is_trivially_copyable? According to the standard, the only types that can be serialized from std::memcpy are those that are trivially copyable; anything else is undefined behavior I assume?

Wouldn’t this then present a problem?

It would actually be nice if the containers had static_asserts for these constraints, you would get compile-time errors then (instead of a RTFM ;))!


#4

No, not quite - String is trivially moveable, but not trivially copyable. That’s enough for SortedSet to work, though.

The juce classes all pre-date this new standards stuff, but it’s something we’ll want to look at again when we finally declare juce to be C++11 only.


#5

Wow @Mayae , very nice C++11 stuff indeed, I didn’t know about all of that.

@jules, thanks for clarifying. Anyway, the doc for SortedSet states that “the element type must be capable of being copied or moved with a straightforward memcpy”. Hence String would not qualify for it.

If you are really really sure that no copy takes place in SortedSet, only moves, then perhaps it would be better to update the doc accordingly, and maybe also add String to the list of explicitly mentioned types for which it is known to work.

Adding the statement that "String is trivially moveable but not trivially copyable" to the doc for String would also be a plus.


#6

Movable as in move-semantics? That’s nice and optimal - but then that will only work in C++11 (where move semantics exists)?

It seems though that all juce container classes are based on HeapBlock internally, that uses realloc() internally - that uses memcpy. That would require T to be trivially copyable to avoid undefined behaviour, no?


#7

No… not quite.

What I mean is that if you memcpy a String, then it’s safe to use the copied version as long as you abandon the old copy. All the juce containers work that way - if they need a copy of an object, they will use the copy constructor, but they can move objects around with memcpy/realloc.