Immutable classes and copy constructors - c++11

I'm making a framework which will read a Tiled's XML file and the resulting object (tpp::File) will be pure immutable (no setters or copy constructors/assignment operators). Basically, it kind of uses the builder pattern idea, but instead of having 2 objects with the same attributes, I'll have one with the main attributes and another that will "wrap" it.
// Represents a Tiled's TMX file. This object is immutable.
class TILEDPP_API File final
{
public:
File() = default;
File(tpp::File&&) = default;
File(const tpp::File&) = delete;
File(const tpp::Path& path, tpp::FileMetadata& metadata);
File& operator = (tpp::File&&) = default;
File& operator = (const tpp::File&) = delete;
const tpp::Path& getPath() const;
const tpp::Header& getHeader() const;
const tpp::Layers& getLayers() const;
const tpp::TileSets& getTileSets() const;
private:
const tpp::Path m_path;
tpp::FileMetadata m_metadata; // Should be const!
};
// Represents the content of a Tiled's TMX file (header, sets, layers etc).
// This struct is non-copyable due to its HUGE size.
struct TILEDPP_API FileMetadata final
{
FileMetadata() = default;
FileMetadata(tpp::FileMetadata&&) = default;
FileMetadata(const tpp::FileMetadata&) = delete;
FileMetadata& operator = (FileMetadata&&) = default;
FileMetadata& operator = (const FileMetadata&) = delete;
tpp::Header header;
tpp::Layers layers;
tpp::TileSets sets;
};
Then, somewhere in the file creation process, we'll have this:
tpp::File FileReader::read(const std::string& path)
{
tpp::FileMetadata metadata = m_parser.parseMetadata(path);
return tpp::File(path, metadata);
}
The above snippet will use the File(const tpp::Path& path, tpp::FileMetadata& metadata) constructor, as expected. However, if we make tpp::File's tpp::FileMetadata const, it will try to use the File(const tpp::File&) constructor instead, which is deleted. Why does it even happen?!
For reference, the project can be found here. Any thoughts are also much appreciated.

it will try to use the File(const tpp::File&) constructor instead
Instead is the wrong word.
As well is the right word.
Prior to C++17, you are creating a temporary File and returning a move-constructed copy from the function. (This move construction may be elided, and in C++17 there is no move constructed copy any more).
FileMetaData does not support a move from FileMetadata const&&). So your =default in File(File&&) doesn't work; no default implementation can work.
Objects cannot be both immutable and practically movable-from.
Immutable objects cannot be practically moved-from in C++; while they are immutable during destruction, move-from happens before destruction, when they must be immutable. So you cannot "tear out their state" and move it somewhere else.
I state this, because you appear to want to support move-from:
File(tpp::File&&) = default;
File& operator = (tpp::File&&) = default;
If you want move-from, File cannot be immutable. If you want immutable, then File cannot be moved-from.
So, suppose you want to keep immutability.
Make those =delete, then change
return tpp::File(path, metadata)
to
return {std::move(path), std::move(metadata)};
and change
File(const tpp::Path& path, tpp::FileMetadata& metadata);
to
File(tpp::Path&& path, tpp::FileMetadata&& metadata);
and your code compiles.
To call read, store the return value in a File&& or a auto&& -- an rvalue reference to the temporary read returns.
Note you cannot store this returned File in a varible of longer lifetime, as that requires moving from the File, which immutable objects do not permit.
Alternatively, back off on immutability. Make it immutable except for moving.
Objects that are immutable except for moving do not store their data as const, because they mutate it when they move. Every other method on them is const.

Related

if i have T&& temp = std::move(other); then use this on a function that accepts T by value

so let's say i have a following function:
void foo(std::string strParam) // pass-by-value
{
// function-body
}
so strParam of foo(string) will either be created via copy (if arg was lvalue) or move (if arg was rvalue).
as everybody knows,
foo("blah"); // rvalue; so string move constructor invoked for strParam.
versus,
string bar = "blah";
foo(bar); // lvalue; so string copy constructor invoked for strParam.
again,
string bar = "blah";
foo(move(bar)); // xvalue; so move constructor.
and for named rvalue reference variable
string &&temp = // can be whatever
foo(temp); // *named* rvalue reference IS a lvalue; so copy constructor.
so i guess what that means is,
string &&movedBar = move(bar);
foo(movedBar); // it actually invokes copy constructor.
so invoking,
foo(move(bar))
is different from
string&& movedBar = move(bar);
foo(movedBar)
because one is unnamed rvalue reference (xvalue) and other is named rvalue reference (lvalue)
that's right, right?
One correction:
foo("blah"); // rvalue; so string move constructor invoked for strParam.
This actually invokes the std::string constructor that takes a const char* and not the std::string move constructor. That is the only std::string constructor in the overload set - everything else would involve more than one user-defined conversion.
On every other point, you are correct. To summarize:
foo("blah"); // calls string constructor that takes a const char*
foo(bar); // calls string copy ctor
foo(move(bar)); // calls string move ctor
string&& movedBar = move(bar);
foo(movedBar); // calls copy ctor
Update: As Tobias points out in the comments, foo("blah") will actually call two constructors, as if it were actually foo(string("blah")). First a temporary string is constructed from "blah" and that temporary is moved into strParam. However that second move will probably be elided, since string strParam(string("blah")) is redundant. This can be verified by delete-ing the move constructor of a custom widget or compiling with -fno-elide-constructors.
Or, as I like to look at it, we were both correct. The const char* is invoked and the string move constructor is invoked (~ish?).

Most efficient way to assign values to a map of maps

Given a map of maps like:
std::map<unsigned int, std::map<std::string, MyBase*>> m_allMyObjects;
What would be the most efficient way to insert/add/"emplace" an element into m_allMyObjects given an unsigned int and a std::string taking optimization into account (on modern compilers)?
What would be the most efficient way to retrieve an element then?
m_allMyObjects may potentially contain up to 100'000 elements in the future.
Common knowledge and folklore about how to efficiently insert into maps (typically telling you to avoid operator[] and prefering the shiny new emplace) considers the costs of constructing and copying the values in the map. In your case, those values are plain pointers which can be copied at virtually no expense, and copying pointers can be aggressively optimized by the compiler.
On the other hand, you actually do have an object that is expensive to handle, namely the key of type std::string. You need to watch out for copies (moved or copied) of the key to determine performance. Obviously, for the tree lookup, you already need the string object, even if you have it as char*, as there is no insertion function that is templated over the type of key. This means for looking up the place to insert, you use one certain std::string object, but once the map node gets created, the new std::string object inside the map is copy-initialized from it (possibly moved). Avoiding everything in excess of that single copy/move should be your goal.
Example time!
#include <map>
#include <cstdio>
struct noisy {
noisy(int v) : val(v) {}
noisy(const noisy& src) : val(src.val) { std::puts("copy ctor"); }
noisy(noisy&& src) : val(src.val) { std::puts("move ctor"); }
noisy& operator=(const noisy& src)
{ val = src.val; std::puts("copy assign"); return *this; }
noisy& operator=(noisy&& src)
{ val = src.val; std::puts("move assign"); return *this; }
int val;
};
bool operator<(const noisy& a, const noisy& b)
{
return a.val < b.val;
}
int main(void)
{
std::map<noisy,int> m;
std::puts("Operator[]");
m[noisy(1)] = 3;
std::puts("insert/make_pair");
m.insert(std::make_pair(noisy(2), 3));
std::puts("insert/make_pair/ref");
m.insert(std::make_pair<noisy&&,int>(noisy(3), 3));
std::puts("insert/pair/ref");
m.insert(std::pair<noisy&&,int>(noisy(4), 3));
std::puts("emplace");
m.emplace(noisy(5), 3);
}
compiled with g++ 4.9.1, -std=c++11, -O2, the result is
Operator[]
move ctor
insert/make_pair
move ctor
move ctor
insert/make_pair/ref
move ctor
move ctor
insert/pair/ref
move ctor
emplace
move ctor
Which shows: avoid everything that creates an intermediate pair containing a copy of the key! Be aware that std::make_pair does never create a pair that contains references, even if it can take the parameters by reference! Whenever you pass a pair containing the copy of the key, the key gets copied into the pair and later into the map.
The expression suggested by MarkMB, namely m[int_k][str_k] = ptr, is quite good, and likely produces optimal code. There is no reason for the first index (int_k) to not use [], as you want a default constructed sub-map if the index is not used yet, so there is no unnecessary overhead. As we have seen, indexing with the string gets away with a single copy, so you are fine. If you can afford to lose your string, m[int_k][std::move(str_k)] = ptr might be a win, though. As discussed in the beginning, using emplace instead of [] is only about the values, which are virtually free to handle in your case.

C++11 - Moving fundamental data types in constructor?

I'm looking into move semantics from C++11 and I'm curious how to move fundamental types like boolean, integer float etc. in the constructor. Also the compound types like std::string.
Take the following class for example:
class Test
{
public:
// Default.
Test()
: m_Name("default"), m_Tested(true), m_Times(1), m_Grade('B')
{
// Starting up...
}
Test(const Test& other)
: m_Name(other.m_Name), m_Times(other.m_Times)
, m_Grade(other.m_Grade), m_Tested(other.m_Tested)
{
// Duplicating...
}
Test(Test&& other)
: m_Name(std::move(other.m_Name)) // Is this correct?
{
// Moving...
m_Tested = other.m_Tested; // I want to move not copy.
m_Times = other.m_Times; // I want to move not copy.
m_Grade = other.m_Grade; // I want to move not copy.
}
~Test()
{
// Shutting down....
}
private:
std::string m_Name;
bool m_Tested;
int m_Times;
char m_Grade;
};
How do I move (not copy) m_Tested, m_Times, m_Grade. And is m_Name moved correctly? Thank you for your time.
Initialization and assignment of a primitive from a prvalue or xvalue primitive has exactly the same effect as initialization or assignment from a lvalue primitive; the value is copied and the source object is unaffected.
In other words, you can use std::move but it won't make any difference.
If you want to change the value of the source object (to 0, say) you'll have to do that yourself.
Looks correct. Except simple data types like bool, int, char are only copied. The point of "moving" a string is that it has a buffer that it normally has to copy when constructing a new object, however when moving the old buffer is used (copying the pointer and not the contents of the buffer).
Test(Test&& other)
: m_Name(std::move(other.m_Name)), m_Times(other.m_Times)
, m_Grade(other.m_Grade), m_Tested(other.m_Tested)
{}

Dependency injection in C++11 without raw pointers

I often use the "dependency injection" pattern in my projects. In C++ it is easiest to implement by passing around raw pointers, but now with C++11, everything in high-level code should be doable with smart pointers. But what is the best practice for this case? Performance is not critical, a clean and understandable code matters more to me now.
Let me show a simplified example. We have an algorithm that uses distance calculations inside. We want to be able to replace this calculation with different distance metrics (Euclidean, Manhattan, etc.). Our goal is to be able to say something like:
SomeAlgorithm algorithmWithEuclidean(new EuclideanDistanceCalculator());
SomeAlgorithm algorithmWithManhattan(new ManhattanDistanceCalculator());
but with smart pointers to avoid manual new and delete.
This is a possible implementation with raw pointers:
class DistanceCalculator {
public:
virtual double distance(Point p1, Point p2) = 0;
};
class EuclideanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return sqrt(...);
}
};
class ManhattanDistanceCalculator {
public:
virtual double distance(Point p1, Point p2) {
return ...;
}
};
class SomeAlgorithm {
DistanceCalculator* distanceCalculator;
public:
SomeAlgorithm(DistanceCalculator* distanceCalculator_)
: distanceCalculator(distanceCalculator_) {}
double calculateComplicated() {
...
double dist = distanceCalculator->distance(p1, p2);
...
}
~SomeAlgorithm(){
delete distanceCalculator;
}
};
Let's assume that copying is not really an issue, and if we didn't need polymorphism we would just pass the DistanceCalculator to the constructor of SomeAlgorithm by value (copying). But since we need to be able to pass in different derived instances (without slicing), the parameter must be either a raw pointer, a reference or a smart pointer.
One solution that comes to mind is to pass it in by reference-to-const and encapsulate it in a std::unique_ptr<DistanceCalculator> member variable. Then the call would be:
SomeAlgorithm algorithmWithEuclidean(EuclideanDistance());
But this stack-allocated temporary object (rvalue-reference?) will be destructed after this line. So we'd need some copying to make it more like a pass-by-value. But since we don't know the runtime type, we cannot construct our copy easily.
We could also use a smart pointer as the constructor parameter. Since there is no issue with ownership (the DistanceCalculator will be owned by SomeAlgorithm) we should use std::unique_ptr. Should I really replace all of such constructor parameters with unique_ptr? it seems to reduce readability. Also the user of SomeAlgorithm must construct it in an awkward way:
SomeAlgorithm algorithmWithEuclidean(std::unique_ptr<DistanceCalculator>(new EuclideanDistance()));
Or should I use the new move semantics (&&, std::move) in some way?
It seems to be a pretty standard problem, there must be some succinct way to implement it.
If I wanted to do this, the first thing I'd do is kill your interface, and instead use this:
SomeAlgorithm(std::function<double(Point,Point)> distanceCalculator_)
type erased invocation object.
I could do a drop-in replacement using your EuclideanDistanceCalculator like this:
std::function<double(Point,Point)> UseEuclidean() {
auto obj = std::make_shared<EuclideanDistance>();
return [obj](Point a, Point b)->double {
return obj->distance( a, b );
};
}
SomeAlgorithm foo( UseEuclidean() );
but as distance calculators rarely require state, we could do away with the object.
With C++1y support, this shortens to:
std::function<double(Point,Point>> UseEuclidean() {
return [obj = std::make_shared<EuclideanDistance>()](Point a, Point b)->double {
return obj->distance( a, b );
};
}
which as it no longer requires a local variable, can be used inline:
SomeAlgorithm foo( [obj = std::make_shared<EuclideanDistance>()](Point a, Point b)->double {
return obj->distance( a, b );
} );
but again, the EuclideanDistance doesn't have any real state, so instead we can just
std::function<double(Point,Point>> EuclideanDistance() {
return [](Point a, Point b)->double {
return sqrt( (b.x-a.x)*(b.x-a.x) + (b.y-a.y)*(b.y*a.y) );
};
}
If we really don't need movement but we do need state, we can write a unique_function< R(Args...) > type that does not support non-move based assignment, and store one of those instead.
The core of this is that the interface DistanceCalculator is noise. The name of the variable is usually enough. std::function< double(Point,Point) > m_DistanceCalculator is clear in what it does. The creator of the type-erasure object std::function handles any lifetime management issues, we just store the function object by value.
If your actual dependency injection is more complicated (say multiple different related callbacks), using an interface isn't bad. If you want to avoid copy requirements, I'd go with this:
struct InterfaceForDependencyStuff {
virtual void method1() = 0;
virtual void method2() = 0;
virtual int method3( double, char ) = 0;
virtual ~InterfaceForDependencyStuff() {}; // optional if you want to do more work later, but probably worth it
};
then, write up your own make_unique<T>(Args&&...) (a std one is coming in C++1y), and use it like this:
Interface:
SomeAlgorithm(std::unique_ptr<InterfaceForDependencyStuff> pDependencyStuff)
Use:
SomeAlgorithm foo(std::make_unique<ImplementationForDependencyStuff>( blah blah blah ));
If you don't want virtual ~InterfaceForDependencyStuff() and want to use unique_ptr, you have to use a unique_ptr that stores its deleter (by passing in a stateful deleter).
On the other hand, if std::shared_ptr already comes with a make_shared, and it stores its deleter statefully by default. So if you go with shared_ptr storage of your interface, you get:
SomeAlgorithm(std::shared_ptr<InterfaceForDependencyStuff> pDependencyStuff)
and
SomeAlgorithm foo(std::make_shared<ImplementationForDependencyStuff>( blah blah blah ));
and make_shared will store a pointer-to-function that deletes ImplementationForDependencyStuff that will not be lost when you convert it to a std::shared_ptr<InterfaceForDependencyStuff>, so you can safely lack a virtual destructor in InterfaceForDependencyStuff. I personally would not bother, and leave virtual ~InterfaceForDependencyStuff there.
In most cases you don't want or need ownership transfer, it makes code harder to understand and less flexible (moved-from objects can't be reused). The typical case would be to keep ownership with the caller:
class SomeAlgorithm {
DistanceCalculator* distanceCalculator;
public:
explicit SomeAlgorithm(DistanceCalculator* distanceCalculator_)
: distanceCalculator(distanceCalculator_) {
if (distanceCalculator == nullptr) { abort(); }
}
double calculateComplicated() {
...
double dist = distanceCalculator->distance(p1, p2);
...
}
// Default special members are fine.
};
int main() {
EuclideanDistanceCalculator distanceCalculator;
SomeAlgorithm algorithm(&distanceCalculator);
algorithm.calculateComplicated();
}
Raw pointers are fine to express non-ownership. If you prefer you can use a reference in the constructor argument, it makes no real difference. However, don't use a reference as data member, it makes the class unnecessarily unassignable.
The down side of just using any pointer (smart or raw), or even an ordinary C++ reference, is that they allow calling non-const methods from a const context.
For stateless classes with a single method that is a non-issue, and std::function is a good alternative, but for the general case of classes with state or multiple methods I propose a wrapper similar but not identical to std::reference_wrapper (which lacks the const safe accessor).
template<typename T>
struct NonOwningRef{
NonOwningRef() = delete;
NonOwningRef(T& other) noexcept : ptr(std::addressof(other)) { };
NonOwningRef(const NonOwningRef& other) noexcept = default;
const T& value() const noexcept{ return *ptr; };
T& value() noexcept{ return *ptr; };
private:
T* ptr;
};
usage:
class SomeAlgorithm {
NonOwningRef<DistanceCalculator> distanceCalculator;
public:
SomeAlgorithm(DistanceCalculator& distanceCalculator_)
: distanceCalculator(distanceCalculator_) {}
double calculateComplicated() {
double dist = distanceCalculator.value().distance(p1, p2);
return dist;
}
};
Replace T* with unique_ptr or shared_ptr to get owning versions. In this case, also add move construction, and construction from any unique_ptr<T2> or shared_ptr<T2> ).

C++11 use-case for piecewise_construct of pair and tuple?

In N3059 I found the description of piecewise construction of pairs (and tuples) (and it is in the new Standard).
But I can not see when I should use it. I found discussions about emplace and non-copyable entities, but when I tried it out, I could not create a case where I need piecewiese_construct or could see a performance benefit.
Example. I thought I need a class which is non-copyable, but movebale (required for forwarding):
struct NoCopy {
NoCopy(int, int) {};
NoCopy(const NoCopy&) = delete; // no copy
NoCopy& operator=(const NoCopy&) = delete; // no assign
NoCopy(NoCopy&&) {}; // please move
NoCopy& operator=(NoCopy&&) {}; // please move-assign
};
I then sort-of expected that standard pair-construction would fail:
pair<NoCopy,NoCopy> x{ NoCopy{1,2}, NoCopy{2,3} }; // fine!
but it did not. Actually, this is what I'd expected anyway, because "moving stuff around" rather then copying it everywhere in the stdlib, is it should be.
Thus, I see no reason why I should have done this, or so:
pair<NoCopy,NoCopy> y(
piecewise_construct,
forward_as_tuple(1,2),
forward_as_tuple(2,3)
); // also fine
So, what's a the usecase?
How and when do I use piecewise_construct?
Not all types can be moved more efficiently than copied, and for some types it may make sense to even explicitly disable both copying and moving. Consider std::array<int, BIGNUM> as an an example of the former kind of a type.
The point with the emplace functions and piecewise_construct is that such a class can be constructed in place, without needing to create temporary instances to be moved or copied.
struct big {
int data[100];
big(int first, int second) : data{first, second} {
// the rest of the array is presumably filled somehow as well
}
};
std::pair<big, big> pair(piecewise_construct, {1,2}, {3,4});
Compare the above to pair(big(1,2), big(3,4)) where two temporary big objects would have to be created and then copied - and moving does not help here at all! Similarly:
std::vector<big> vec;
vec.emplace_back(1,2);
The main use case for piecewise constructing a pair is emplacing elements into a map or an unordered_map:
std::map<int, big> map;
map.emplace(std::piecewise_construct, /*key*/1, /*value*/{2,3});
One power piecewise_construct has is to avoid bad conversions when doing overload resolution to construct objects.
Consider a Foo that has a weird set of constructor overloads:
struct Foo {
Foo(std::tuple<float, float>) { /* ... */ }
Foo(int, double) { /* ... */ }
};
int main() {
std::map<std::string, Foo> m1;
std::pair<int, double> p1{1, 3.14};
m1.emplace("Will call Foo(std::tuple<float, float>)",
p1);
m1.emplace("Will still call Foo(std::tuple<float, float>)",
std::forward_as_tuple(2, 3.14));
m1.emplace(std::piecewise_construct,
std::forward_as_tuple("Will call Foo(int, double)"),
std::forward_as_tuple(3, 3.14));
// Some care is required, though...
m1.emplace(std::piecewise_construct,
std::forward_as_tuple("Will call Foo(std::tuple<float, float>)!"),
std::forward_as_tuple(p1));
}

Resources