Removing copy ctor of 3rd party class - c++

I have a class that stores a large std::map. My understanding is that the idiomatic way to do this is:
class Foo {
public:
Foo(/* Note: passed by value */ std::map<Bar, Baz> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(std::move(large_map));
}
This transfers the ownership of large_map from main, to the constructor arg and then to Foo's member. The problem with this is that the code is hard to use properly and I discovered that someone somewhere created a Foo and forgot to move the map into the ctor:
void deep_dark_hidden_code() {
std::map<Bar, Baz> large_map;
// Work hard to initialize large_map.
Foo foo = Foo(large_map); // Whoops! The author of this code forgot to std::move
}
I am looking for a way to write Foo which protects against such mistakes. My first thought was to use unique_ptr
class Foo {
public:
Foo(std::unique_ptr<std::map<Bar, Baz>> large_map_ptr) : large_map_(std::move(*large_map_ptr)) {}
private:
std::map<Bar, Baz> large_map_;
};
int main() {
std::unique_ptr<std::map<Bar, Baz>> large_map_ptr = new std::map<Bar, Baz>;
// Work hard to initialize large_map_ptr.
Foo foo = Foo(std::move(large_map_ptr));
}
This code is essentially using unique_ptr as a hack to erase the copy constructor of std::map. My question is whether there is a more explicit way to do this. Some magic template make_uncopyable like:
class Foo {
public:
Foo(make_uncopyable<std::map<Bar, Baz>> large_map) : large_map_(std::move(large_map)) {}
private:
std::map<Bar, Baz> large_map_;
};
The desired effect is to leave the code in my main intact but prevent the code in deep_dark_hidden_code from compiling.

The title appears to be a slight misnomer here (or is at least at odds with the contents with your question):
(At least in the example given), you do not want to remove the copy constructor i.e. Foo::Foo(const Foo& other), but rather prevent invokation of Foo's constructor with a non-movable argument.
As Mestkon pointed out (all credit to them - if they want to post it as an answer, just give me a yell and I'll remove mine), you could change Foo's constructor to require a std::map<Bar, Baz>&& large_map i.e.
Foo(std::map<Bar, Baz>&& large_map) : large_map_(std::move(large_map)) {}
A test at Godbolt confirms that the compiler will refuse to accept the Foo foo = Foo(large_map); in the deep_dark_hidden_code()., demanding the argument to be movable (as desired). This this might still run the risk of others "fixing" their code by simply slapping a std::move() around their large_map... and then attempting to continue using it after constructing Foo with it.
If you want really want to prevent the invokation of the copy constructor (here std::map), things become rather difficult, as you cannot change the the definition std::map to erase its copy constructor. I don't feel I have a good answer to this.

Related

C++ static factory method vs constructor: how to avoid copying?

This question asks for a clean way of implementing a static factory method in C++, and this answer describes a clear way to do so. Return Value Optimization would save us from making an unnecesary copy of Object, thus making this way of creating an Object as efficient as directly invoking a constructor. The overhead of copying i to id inside a private constructor is negligible because it's a small int.
However, the question and answer don't cover a more complex case when Object contains an instance variable that is an instance of class Foo (that requires complex initialization logic) rather than a small primitive type. Suppose I want to construct Foo using the arguments passed to Object. A solution using a constructor would look something like:
class Object {
Foo foo;
public:
Object(const FooArg& fooArg) {
// Create foo using fooArg here
foo = ...
}
}
An alternative with a static factory method analogous to the quoted answer would be, as it appears to me:
class Object {
Foo foo;
explicit Object(const Foo& foo_):
foo(foo_)
{
}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(foo);
}
}
Here, the overhead of copying foo_ to foo is no longer necessarily negligible, since Foo can be an arbitrarily complex class. Moreover, as far as I understand (C++ newbie here so I may be wrong), this code implicitly requires for a copy constructor to be defined for Foo.
What would be a similarly clean but also efficient way of implementing this pattern in this case?
To anticipate possible questions about why this is relevant, I consider having constructors with logic more complicated than just copying the arguments to be an anti-pattern. I expect the constructor to:
be guaranteed to work and not throw exceptions,
and not do heavy calculations under the hood.
Thus, I prefer to put complex initialization logic into static methods. Moreover, this approach provides additional benefits such as overloading by static factory method name even when the input argument types are the same, and the possibility of clearly stating what is being done inside in the name of the method.
Thanks to move constructor, you might do:
class Object {
Foo foo;
explicit Object(Foo&& foo_) : foo(std::move(foo_)) {}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
Foo foo = ...
return Object(std::move(foo));
}
};
If Foo is not movable, wrapping it in smart pointer is a possibility:
class Object {
std::unique_ptr<Foo> foo;
explicit Object(std::unique_ptr<Foo>&& foo_) : foo(std::move(foo_)) {}
public:
static Object FromFooArg(const FooArg& fooArg) {
// Create foo using fooArg here
std::unique_ptr<Foo> foo = ...
return Object(std::move(foo));
}
};
What is wrong with initializing the instance in the constructor directly from the arguments needed to do so?
class Object
{
Foo foo; // or const Foo foo, disallowing assignment
public:
explicit Object(FooCtorArgs const&fooArg,
const AdditionalData*data = nullptr)
: foo(fooArg) // construct instance foo directly from args
{
foo.post_construction(data); // optional; doesn't work with const foo
}
static Object FromFooArg(FooCtorArgs const&fooArg,
const AdditionalData*data = nullptr)
{
return Object{fooArg,data}; // copy avoided by return value optimization
}
};
AFAICT, there is no need to copy/move anything, even if you need to adjust foo post construction.

In-class / constructor member initialization

I'll try to summarize what I need in both words and code snippets.
I have a class, Foo, which contains a data member of the type Bar:
class Foo {
public:
Bar instance_of_Bar;
Foo (int some_data)
{
// I need to initialize instance_of_Bar using one of its
// constructors here, but I need to do some processing first
// This is highly discouraged (and I prefer not to use smart pointers here)
instance_of_bar = Bar(..);
// As an unrelated question: will instance_of_Bar be default-initialized
// inside the constructor before the above assignment?
}
}
Obviously, the "correct" way to do it would be to use an initializer list like this:
Foo (int some_data) : instance_of_Bar(some_data) {}
But this is not an option because I need to do some work on some_data before passing it to the Bar constructor.
Hopefully I made myself clear. What would be the RAII way of doing it with minimal overhead and copying (The Bar class is a hefty one).
Thanks a bunch.
"But this is not an option because I need to do some work on some_data before passing it to the Bar constructor."
What about providing another function to "do some work on some_data":
Foo (int some_data) : instance_of_Bar(baz(some_data)) {}
int baz(int some_data) {
// do some work
return some_data;
}

C++ facade avoiding copies

Consider the following, simplified facade pattern:
class Foo {
public:
int times;
int eval(const int val) { return val*times; }
};
class Bar {
Foo foo;
public:
Bar(const Foo& f) : foo(f) {}
double eval(const double val) { return val * foo.times; }
};
Obviously, an instance of Bar is only required to evaluate a special (i.e. double-valued) interpretation of Foo's eval() method. A Bar won't have any other members except the foo it forwards to.
For safety reasons I have not used a const reference or a pointer inside Bar (I just don't know yet if at some point a Bar instance might escape from a stack frame, so resource management is important).
My question here is two fold:
Can the C++ compiler possibly detect that Bar is merely a facade and
"inline" the member access?
Is there a (safe) way to prevent copying
of the passed object?
On some platforms (gcc/clang) you can force inlining with the attribute always_inline or emit warnings should a function not be inlined.
No, if you don't want to copy, you need to guarantee the life-time of the object elsewhere. If you consider this to be unsafe, don't do it. What you can do is move an object. This avoids copies and life-time issues, but might not be possible with your compiler.
For example:
struct Bar {
// Only accept rvalues of Foo
explicit Bar(Foo&& f) : f(std::move(f)) {}
Foo f;
};
1- Yes, the compiler will most probably inline the function [It depends on compiler).
2- Always stick to RAII. In C++3, Foo object foo shall be either member variable (as you did), or managed pointer (copied at copy constructor and assignment operator and deleted at destructor). In C++11 you can use right value reference.
NOTE: This example is not a facade!

Named constructors and temporary lifetime extension

I'm looking for a way to define a "base" constructor, that will initialize values using defaults, and then extend that base into a number of specialized constructors.
The pseudocode of what I want might look like:
class Foo{
private:
int val;
/* ... */
public:
// Base constructor
Foo(){ /*...*/ } // This provides basic initialization of members
// Named constructors
static Foo fromString(string s){
Foo f; // Call base constructor
f.val = s.length(); // Customize base object
return f; // Return customized object
}
static Foo fromInt(int v){
Foo f;
f.val = v;
return f;
}
}
At first, I thought about extending the lifetime of the temporary f, but the const declaration prevents me from editing its members. So it seems this is out.
Then I tried the "named constructor" approach (which is shown above). However, I had to modify the example to create the object first, then modify it, then return it. This seems to work, but I'm reasonably confident that it is just a coincidence since f is a temporary and goes out of scope at the end of the function.
I've also considered using something like auto_ptrs, but then I'm working with both Foo objects as well as auto_ptrs to Foo, and this makes the rest of the code "care" whether objects are created via the base constructor (in which case it would be an object) or via one of the extended constructors (in which case it would be a pointer).
If it helps, in Python, I would use something like this:
class Foo(object):
def __init__(self):
/* Basic initialization */
#classmethod
def fromString(cls, s):
f = Foo() #†
f.val = len(s)
return f
Lastly, there are two reasons I want to do it this way:
Code reuse, I would like to move the common initialization out of each of the constructors and into one. I realize I can do this via an init()-type private method called by each constructor, but I just wanted to mention this.
Clarity and resolve ambiguity. Much like the motivation for the named constructor example, parameter types by themselves aren't enough to determine which ctor should be used. Additionally, the fromSomething syntax provides excellent clarity.
Forgive me if there is a simple solution, my work has shifted from c++ to Java/Python for the past few years so I'm a bit rusty.
This is perfectly valid:
static Foo fromInt(int v){
Foo f;
f.val = v;
return f;
}
This invokes Foo's copy constructor when you return f(probably the compiler applies return value optimization, so no copies are made). f goes out of scope, but the return value is just a copy of it, so this is totally valid, it's not just "a coincidence" that it's working.
So if your worries about using the named constructor approach is just that you don't really know if it works, go ahead with it, it works perfectly.
In C++11, you can call other constructors from constructors:
struct X{
X() : ... { ... }
X(int i) : X() { ... }
X(std::string s) : X() { ... }
};
For C++03, the named constructor approach is likely the best and perfectly reasonable, IMHO.
Why not:
class Foo{
private:
int val;
void Init(int v = <some default value>/*What ever here *));
/* ... */
public:
// Base constructor
Foo(){ Init(); } // This provides basic initialization of
Foo(string &s) { Init(s.length); };
Foo(int v) { Init(v); };
};
Seems simpler.

Writing a source function in c++11 properly

My head hurts: I've read so many blogs about C++11x's move semantics that my brain's gone mushy, so please can someone give me a short-but-sweet guide on how to make the following code work efficiently? Given a class Foo, I want to be able to write functions that return Foo objects in different states (sometimes called source functions), and to do this as efficiently as possible.
class Foo {
// Some methods and members
};
Foo getFirstFoo() {
Foo foo;
// Do some things to foo
return foo;
}
Foo getSecondFoo() {
Foo foo;
// Do some different things to foo
return foo;
}
int main() {
Foo f = getFoo();
// use f ...
f = getSecondFoo();
// use f ...
return 0;
}
I don't want to modify Foo much, and the idea is to allow all sorts of Foo objects to be created through a variety of non-member source functions, so adding ever more constructors would be missing the point.
In C++03 my options would be to wrap the returned object in an auto_ptr (a big downside being that the recipient code needs to know to handle a smart pointer), or to cross my fingers and hope that some sort of optimization might take place (likely for the first line in main, less so for the second). C++11x seems to provide something better through move semantics, but how would I take advantage of these? So I need to change the way objects are returns in the source functions, or add some move constructor to Foo, or both?
This is already optimal1, provided that move constructors are generated2:
class Foo {
public:
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
};
Returned values are rvalue references by default.
1 Well.... provided that your class Foo benefits from move construction at all. Remember, move is an optimization of copy. Some copies cannot be improved! E.g, unsuited:
struct Foo { int data; };
struct Foo2 { int data[5<<10]; };
well suited:
struct Foo3 { std::vector<std::string> data; };
See Move semantics - what it's all about? for a more general background on things like this.
2 Not all compilers do support that yet (even if they do implement rvalue references), so you might have to write the
move constructor
move assignment