RAII way to choose between two constructors - c++

I have a class that holds a large table of data, with a constructor that takes all of the parameters needed to calculate that data. However, it takes a long time to run, so I've added a constructor that takes a stream, and reads the data in from that stream. I'm having trouble coming up with a RAII way of designing this class though, since I have two constructors, and at run time I need to choose between them. This is what I've come up with:
std::string filename; // Populated by command line arguments
DataTable table; // Empty constructor, no resource acquisition or initialization
if( filename.empty() ) {
table = DataTable(/*various parameters*/);
} else {
std::ifstream filestream(filename);
table = DataTable(filestream); // Reads from file
}
That looks pretty fragile to me. The default constructor will leave the object in a valid state, but a useless one. The only use of it is to create a "temporary" object in the outer scope, to be assigned to in one of the branches of the if statement. Additionally, there's a flag "inited" behind the scenes to manage if the object was default-constructed or fully initialized. Is there a better way to design this class?

Maybe like this:
DataTable foo = filename.empty()
? DataTable(x, y, z)
: DataTable(std::ifstream(filename));

Move the file test code that decides which way to init into the ctor, move the ctors into two private init functions, call one of these from the ctor or throw an exception if everything fails.

Some thoughts:
Get rid of the "inited" flag.
Get rid of the default constructor if it can't sensibly construct the object
use this kind of construct to get you a DataTable:
DataTable get_me_my_data_fool(ParameterTypes... params, const string& filename = "")
{
if(!filename.empty())
return DataTable(std::ifstream(filename)); // check if file exists!
else
return DataTable(params...);
}
Actually, now that I think about it, it would be better to just put this logic into the DataTable constructor.

If the class supports copy, then Kerrek SB's solution is the way
to go. From what you say, however, copying is expensive. In
that case, and you can use C++11, you might try adding a move
constructor, in order to avoid the deep copy. Otherwise, you're
probably stuck allocating dynamically:
std::auto_ptr<DataTable> fooPtr( filename.empty()
? new DataTable( x, y z )
: new DataTable( filename ) );
DataTable& foo = *fooPtr;

Here's another idea for completeness sake:
template<typename T>
class uninitialised
{
public:
~uninitialised()
{
if (alive_) {
operator T&().~T();
}
}
template<typename... Ts>
void create(Ts&&... args)
{
assert(!alive_ && "create must only be called once");
void* const p = obj_;
::new(p) T(std::forward<Ts>(args)...);
alive_ = true;
}
operator T&()
{
assert(alive_ && "T has not been created yet");
return *reinterpret_cast<T*>(obj_);
}
private:
bool alive_ = false;
alignas(T) unsigned char obj_[sizeof(T)];
};
// ...
std::string filename;
uninitialised<DataTable> table;
if (filename.empty()) {
table.create(/* various parameters */);
} else {
std::ifstream filestream(filename);
table.create(filestream);
}
DataTable& tbl = table;

Related

Workaround for returning uncopyable object without a move ctor

In my API I have a function that returns std::istringstream.
The std::istringstream class is non-copyable but supports moving so on a conforming compiler there is no problem returning a local std::istringstream.
However, on gcc 4.9, there is no support for moving std::istringstream.
Is there some workaround that I can use that std::istringstream without changing the API from the user's perspective?
The workaround suggested here, of using a unique_ptr<std::istringstream> will change the semantics of the API.
If you can't move the std::istringstream, there's no much way around it.
If an object is non copiable and non movable, you can't return it by value.
If you want to support new features, you better get a new compiler for those.
In the meatime, you could return a unique_ptr. If you're really eager to return by value, you could return a movable wrapper that contains a std::unique_ptr<std::istringstream> and provide the same interface as a istringstream. However, this also affect the return type.
It may be tempting to return by rvalue reference. Here's what you can do:
struct MyApiClass {
std::istringstream&& get_stream() {
return std::move(*_stream);
}
private:
std::unique_ptr<std::istringstream> _stream;
};
Then, with your old compiler, you can use it like this:
std::istringstream&& stream = myApiClass.get_stream();
// use stream as long as myApiClass exists
People using a new compiler will be able to use it like that:
std::istringstream stream = myApiClass.get_stream();
// use stream normally
This is the way the api is less affected. Other than that, I don't know any workaround.
The way to return class without move/copy constructor is to use the return statement with braced-init-list:
class C {
C() = default;
C(const C&) = delete;
C(C&&) = delete;
};
C make_C() { return {}; }
int main() {
C&& c = make_C();
}
Demo
Unfortunately, only non-explicit constructor are considered for this initialization and std::istringstream have explicit constructor.
One workaround is to create a sub-class with non explicit constructor:
struct myIStringStream : std::istringstream
{
myIStringStream () = default;
};
myIStringStream make_istringstream()
{
return {};
}
int main()
{
std::istringstream&& iss = make_istringstream();
}
Demo
Answering my own question for completeness and future reference.
The goal was to find a workaround for the gcc (< 5) bug where std::istringstream does not provide a move ctor that will work in cases where I want to return the un-copyable and (bugly-) unmovable stream.
As mentioned in the comments, I can in fact change my function signature (at least on gcc < 5) to return a proxy object that allows copying or moving without changing the API for code used on newer/other compilers.
The idea, suggested and implemented by a colleague, is to create a proxy object around std::istringstream which provides a similar API, but also provides a copy-ctor which manually creates and initializes a new internal std::istringstream from the copied-from stream. This proxy is used only on the offending compilers.
The code in its natural habitat is here.
Here's the relevant part:
#if !defined(__GNUC__) || (__GNUC__ >= 5)
using string_stream = std::istringstream;
#else
// Until GCC 5, istringstream did not have a move constructor.
// stringstream_proxy is used instead, as a workaround.
class stringstream_proxy
{
public:
stringstream_proxy() = default;
// Construct with a value.
stringstream_proxy(std::string const& value) :
stream_(value)
{}
// Copy constructor.
stringstream_proxy(const stringstream_proxy& other) :
stream_(other.stream_.str())
{
stream_.setstate(other.stream_.rdstate());
}
void setstate(std::ios_base::iostate state) { stream_.setstate(state); }
// Stream out the value of the parameter.
// If the conversion was not possible, the stream will enter the fail state,
// and operator bool will return false.
template<typename T>
stringstream_proxy& operator >> (T& thing)
{
stream_ >> thing;
return *this;
}
// Get the string value.
std::string str() const { return stream_.str(); }
std::stringbuf* rdbuf() const { return stream_.rdbuf(); }
// Check the state of the stream.
// False when the most recent stream operation failed
operator bool() const { return !!stream_; }
~stringstream_proxy() = default;
private:
std::istringstream stream_;
};
using string_stream = stringstream_proxy;
#endif

How do I return an immutable parameter from a method, unchanged, and without a copy in c++?

How do I return a parameter from a method, unchanged, and without a copy in c++?
// This is more or less the desired signature from the caller's point of view
SomeImmutableObject ManipulateIfNecessary(SomeImmutableObject const& existingObject)
{
// Do some work…
// ...
if (manipulationIsNeccessary)
{
// Return a new object with new data etc (preferably without another copy)...
return SomeImmutableObject(...);
}
else
{
// Return the original object intact (but with no further copies!)...
return existingObject;
}
}
An example is C#'s String.Trim method. C# strings are immutable and if Trim doesn't have to do any work, a reference to the existing string is returned, otherwise a new string object with the trimmed content is returned.
How would I mimic this semantic in C++ given something close to the above method signature?
Your object must be a reference type for this to work. Let's give a toy example for strings:
class RefString {
public:
RefString() : ref(new std::string()) { }
RefString(const std::string& str) : ref(new std::string(str)) { }
RefString trim_trailing_newline() {
if (ref->back() == '\n') {
return RefString(ref->substr(0, ref->size()-1));
}
return *this;
}
size_t size() { return ref->size(); }
private:
std::shared_ptr<std::string> ref;
};
int main(int argc, char** argv) {
RefString s("test\n");
std::cout << s.size() << "\n";
std::cout << s.trim_trailing_newline().size() << "\n";
return 0;
}
You may always return const SomeImmutableObject&. Note though that assigning result to an object will invoke a copy.
SomeImmutableObject x = ManipulateIfNecessary(y); // will invoke a copy-ctor
The real trick would be the implementation. When the first "if" clause has an effect you will be presumably returning reference to temporary variable (bad thing to do). The newly created object would have to be dynamically allocated.
All, in all I do not think this is easily possible w/o some smart memory management.
A reasonable option is to implement SomeImmutableObject in a way that supports this - internally as a reference-counted smart-pointer to the logical state, while externally it may provide value semantics. (This can complicate usage from threaded code - you may want to read up on copy-on-write (COW) and why it became unpopular for implementing std::string.)
If you're stuck with an existing SomeImmutableObject implementation you can't change, and you can't wrap it with a reference-counted smart-pointer of sorts, then choices get limited.
It doesn't provide as clean caller usage, but you could make manipulationIsNeccessary a caller-accessible function, then have the caller call the "new object with new data" code - in a second function:
SomeImmutableObject obj;
const SomeImmutableObject& o =
manipulationIsNecessary(obj) ? newObjectWithNewData(obj) : obj;
...use o...
By having newObjectWithNewData be a separate function, you should get return value optimisation kicking in (though it's always best to check with your compiler/settings).

C++: Immutable method versions

In C++11, what is the best way to provide two versions of a method, one to modify the object itself and one to return a modified copy?
For example, consider a string class which has the "append(string)" method. Sometimes you might want to use append to modify your existing string object, sometimes you might want to keep your string object the same and create a copy.
Of course, I could just implement the first version and manually create a new object everytime I need one but that adds multiple temporary variables and lines of code to my project.
If it is still not clear what I am trying to do:
String s1("xy");
String s2 = s1.appendCopy("z");
s1.appendThis("w");
// s1 == "xyw"
// s2 == "xyz"
In Ruby there is a concept (or rather, a naming convention) which says for such methods, there are two variants: append (creates a new String) and append! (modifies this object)
C++ does not have something like this, so I would be stuck with ugly method names like "appendCopy".
Is there a good way to implement what I am trying to do?
So far, the best idea I had would be to make the modifying versions class members and the copying/immutable versions static methods which take the object to work on as a const argument.
There is actually a guideline, expressed by Herb Sutter in GotW #84:
Prefer non-member non-friend functions.
In your specific case, append (in-place) requires modifying the existing string so is well-suited to be a class-method, while append (copying) does not, so (following the guideline) should not be a class-method.
Thus:
void std::string::append(std::string const&);
inline std::string append(std::string left, std::string const& right) {
left.append(right);
return left;
}
After popular request, here are two overloads that can be used to optimize performance. First the member-version that may reuse its argument's buffer:
void std::string::append(std::string&& other) {
size_t const result_size = this->size() + other.size();
if (this->capacity() < result_size) {
if (other.capacity() >= result_size) {
swap(*this, other);
this->prepend(other);
return;
}
// grow buffer
}
// append
}
And second the free-function that may reuse its right-hand buffer:
inline std::string append(std::string const& left, std::string&& right) {
right.prepend(left);
return right;
}
Note: I am not exactly sure there are not ambiguous overloads manifesting. I believe there should not be...
With the new move semantics you can write:
class A{
public:
// this will get the property
const dataType& PropertyName() const { return m_Property; }
// this wil set the property
dataType& PropertyName() { return m_Propery; }
private:
dataType m_Propery;
};
main()
{
A a;
a.PropertyName() = someValueOfType_dataType; // set
someOtherValueOfType_dataType = a.PropertyName(); // get
}

Object creation in constructor

I somehow read that it is bad style to do object-creation in a constructor ... however, I forgot why it was considered to be bad style (especially when using dependency injection).
Here an example of object-creation in the constructor as pseudo-code:
Myclass
{
Myclass(MyMemberFactory& fac)
{
for(Some criteria)
push_back(fac.createMyMemberType());
}
vector<MyMemberType*> getMyMember();
{
return myMember_;
}
...
private:
vector<MyMemberType*> myMember_;
}
So you can use unit-testing without problems, because you can mock-away the MyMemberFactory.
If I would move the for-loop in an seperated initialize-method, it would be necesarry to check for double-initialisation, and all getters would need first to ckeck, if initialisation already was done. Here the code, by using a seperate initialisation:
Myclass
{
Myclass() : isInitialized_(false)
{
}
void initialize(MyMemberFactory& fac);
{
if(isInitialized_)
throw "Error: Double-Init is not permitted.";
for(Some criteria)
push_back(fac.createMyMemberType());
isInitialized_ =true;
}
vector<MyMemberType*> getMyMember();
{
if(isInitialized_)
throw "Initialize first!";
return myMember_;
}
...
private:
vector<MyMemberType*> myMember_;
bool isInitialized_;
}
So do know any reason, why I should use the second approach over the first approach? Or maybe I just had something wrong in mind, and the first approach is perfectly ok?
If the constructor throws an exception, the destructor will not be called, thus you will lose all the memory that you manually allocated.
The first approach is actually fine. It's not that object creation in a constructor is problematic, it's that doing so with a constructor is problematic. So
Myclass()
{
MyMemberFactory fac;
for(Some criteria)
push_back(fac.createMyMemberType());
}
Would be problematic since clients can no longer use a different factory (for testing, for instance).

Create objects in conditional c++ statements

I am learning c++, and I just got to the object oriented chapter. I have a question about creating objects inside if statements.
The problem I'm working on says to create a class that will display a report header. The class has a default constructor that sets the company name and report name to a generic thing, and also, if the user wants, has a constructor that takes two arguments (strings company name and report name).
The problem says, specifically, "A two-parameter default constructor should allow these [company and report names] to be specified at the time a new Report object is created. If the user creates a Report object without passing any arguments, use the default values. Otherwise, use user specified values for the names."
So my question is, how to create these objects? I understand how to create an object without any arguments (i.e. Report newobj;), and also with arguments (i.e. Report newobj(string string);). Basically, I get how to create these objects initially at the top of my main function. But is it possible to create them inside if statements based on user choices? Here is what I have so far and, obviously, it doesn't work:
#include <iostream>
#include <string>
#include "report.h"
using namespace std;
bool enter_company_name(); // return true if user wants to enter company name
bool print_form(); // return true if user wants to print in formatted output
int main()
{
string company_name,
report_name;
bool name = false,
format = false;
name = enter_company_name();
format = print_form();
if (name)
{
cout << "Enter company name: ";
getline(cin, company_name);
cout << "Enter report name: ";
getline(cin, report_name);
Report header(company_name, report_name); // THIS IS MY PROBLEM
}
else
Report header; // THIS IS MY PROBLEM
if (format)
header.print_formatted();
else
header.print_one_line();
return 0;
}
bool enter_company_name()
{
char choice;
cout << "Do you want to enter a name?\n>";
cin >> choice;
if (choice == 'y' || choice == 'Y')
return true;
else
return false;
}
bool print_form()
{
char choice;
cout << "Do you want to print a formatted header?\n>";
cin >> choice;
if (choice == 'y' || choice == 'Y')
return true;
else
return false;
}
So I want to create an object using default values if none are specified, or create one with the user values if that's the choice given. I just can't figure out how to do it interactively in c++. I have not been able to find any similar questions anywhere so far.
The closest thing I've come across uses pointers to do something similar to what I want to do, but the book I'm using has not gotten to pointers yet, and I want to try to figure out a way to do it that stays within the bounds of the chapter I'm working in (i.e. not using pointers).
I didn't include the header file or class implementation file because I don't think they are relevant here.
Thank you in advance!
First off, you cannot create an object within a conditional statement and use it after the conditional statement: the two branches of the conditional statement create a scope each and any object created within in destroyed a the end of the branch. That is, you need to come up with a different approach. The simplest approach is probably to delegate the creation of the object to a function which returns the objects as appropriate:
Report makeReport() {
if (enter_company_name()) {
...
return Report(name, company);
}
return Report();
}
...
Report report = makeReport();
An alternative approach is to use the ternary operator to conditonally create the Report one way or another:
bool get_company_name = enter_company_name();
std::string name(get_company_name? read_name(): "");
std::string company(get_company_name? read_company(): "");
Report report = get_company_name? Report(name, company): Report();
All of these approaches assume that the Report class is actually copyable.
I don't know if I understood your question correctly but can't you just declare report before the if/else block and then initialize inside it?
Report header;
if (...) {
header = Report();
else
header = Report(name,company);
Or in a shorter way:
Report header; // calls default constructor
if (shouldInitializeWithParams) {
header = Report(name,company);
}
Of course this requires you to have the empty constructor defined.
We don't know whether class Report is copy-able, so better to use pointers.
Report * header;
if (...) {
header = new Report();
else
header = new Report(name,company);
// after all don't forget
delete header;
and of course you should use header pointer like that
header->print_formatted();
The simplest thing that comes to mind is performing a little refactoring on the code flow. Create a function that processes the input and returns the constructed object:
Report loadReport() {
if (user_input()) {
// read input
return Report(name,company);
} else {
return Report();
}
}
Then call the function from main. The small change in the design is the introduction of a function whose single responsibility is creating a Report from user input, which actually makes sense as a function.
You can use an rvalue reference to bind in place to either constructed object.
struct Foo
{
Foo(int bar): bar(bar) {}
int bar
};
Foo&& f = condition ? Foo(4) : Foo(5);
f.bar = 1000;
I'm not sure if I understood your question properly. Apologies if you read the answer and realise that that's the case.
But nevertheless, I think the main strategy would be to make use of constructor overloading. ie, you define constructors for both: the case when no parameters are passed and the case when parameters are passed.
The former(what you refer to as default constructor) will initialise the company and report names to default values. The latter will assign the parameters received, to the comapany and report names.
As for the use of pointers: you can avoid it by 'declaring' a lot of objects of type 'Report'(class). For eg, you can create an array of header(objects).
And then you can 'define' it as and when the user responds.
But by using pointers, you're doing everything in runtime(dynamic assignment) whereas when using arrays(or declaring many objects): the amount is fixed. This can be inefficient.
As of C++17, you can now use std::optional for this task - it avoids dynamic memory allocation, it avoids two-phase construction of the object, and it doesn't require the type to be movable or copyable. It allows you to delay the construction of the object while keeping it on the stack and also still being exception-safe. If you construct it in every branch you can safely use it afterward with no performance penalty. It will also work as a class member allowing you to avoid the problem with the class constructor initializer for it, unlike the rvalue reference solution. Demo: https://gcc.godbolt.org/z/vbe5eh
#include <optional>
struct UseCtorA final {};
struct UseCtorB final {};
struct Report final
{
Report() = delete;
Report(Report const &) = delete;
Report(Report &&) = delete;
Report &operator=(Report const &) = delete;
Report &operator=(Report &&) = delete;
Report(UseCtorA, char c) : v{1} { if(c == 't'){ throw 3; } }
Report(UseCtorB) : v{2} {}
constexpr auto getValue() const noexcept { return v; }
private:
int v;
};
int main(int nargs, char const *const *args)
{
std::optional<Report> report;
if(nargs > 2)
{
report.emplace(UseCtorA{}, args[1][0]);
}
else
{
report.emplace(UseCtorB{});
}
return report->getValue();
}
If you are stuck in an older compiler that only supports C++11, you can make your own really dumb version of std::optional for this express purpose by using a union and placement new:
struct Empty final {};
template<typename T>
struct Optional
{
Optional() noexcept : unused{} {}
~Optional() noexcept(noexcept(v.~T()))
{
if(constructed_successfully)
{
v.~T();
}
}
template<typename... Args>
auto emplace(Args &&... args) -> T &
{
if(constructed_successfully)
{
v.~T();
constructed_successfully = false;
}
T &r = *new (&v) T(std::forward<Args>(args)...);
constructed_successfully = true;
return r;
}
auto operator->() noexcept -> T *
{
return &v;
}
private:
union
{
T v;
[[no_unique_address]] Empty unused;
};
bool constructed_successfully = false;
};
The generated assembly is identical to with std::optional: https://gcc.godbolt.org/z/vzGz9E
Though, I would recommend using an existing library to supplement your lack of access to std::optional instead of rolling your own like I have done above - my version doesn't work for copying or moving.