How does std::optional delay initialization? / How is std::optional implemented? - c++

Lately I've taken interest in initialization. One of the things I'm particularly interested in, is std::optional for its ability to initialize an instance of a type after it's been declared. I have tried reading the code inside the optional header, but the code is just too 'bombastic' for me to comprehend.
How is std::optional able to delay the initialization of an object on the stack? I assume it just reserves sizeof(<whichever_type) number of bytes on the stack, and then reinterprets those bytes for the initialization of <whichever_bytes>. But how does it do that specificially? How is it implemented? How can I implement that myself?
Edit: to clarify, I know that std::optional basically has a bool member to keep track of whether the object is initialized or not, and another member, which contains the data.
What I don't understand, however, is how optional is able to manually initialze something.
How is it able to destruct an object? How is it able to reconstruct a new one again after the old one is destructed?

The "obvious" way to represent an std::optional<T> is to use an indication whether the value is set together with a union containing a T, i.e., something like this:
template <typename T>
class optional {
bool isSet = false;
union { T value; };
public:
// ...
};
By default the members in the union are not initialized. Instead, you'll need to use placement new and manual destruction to manage the life-time of the entity within the union. Conceptually that is similar to using an array of bytes but the compiler handles any alignment requirements.
Here a program with some of the operations shown:
#include <iostream>
#include <memory>
#include <string>
#include <utility>
#include <cassert>
template <typename T>
class optional {
bool isSet = false;
union { T value; };
void destroy() { if (this->isSet) { this->isSet = true; this->value.~T(); } }
public:
optional() {}
~optional() { this->destroy(); }
optional& operator=(T&& v) {
this->destroy();
new(&this->value) T(std::move(v));
this->isSet = true;
return *this;
}
explicit operator bool() const { return this->isSet; }
T& operator*() { assert(this->isSet); return this->value; }
T const& operator*() const { assert(this->isSet); return this->value; }
};
int main()
{
optional<std::string> o, p;
o = "hello";
if (o) {
std::cout << "optional='" << *o << "'\n";
}
}

Related

How to associate object with its type

I'm trying to create a statistics system in C++ which will allow me to associate a string with a value of an arbitrary type. Currently, I have it working with an enum that keeps track of the type and a void * that points to the object, but this requires me to make individual if statements for all of the types I want to support. I'd like to have it so that I can support any arbitrary type using some kind of template. I've created some test code that sort of works, but there are issues:
class Test {
std::type_index type;
void *value;
public:
template <typename T>
Test(T val) : type(typeid(val)) {
T *val_p = new T;
*val_p = val;
value = (void *)val;
}
Test() : type(typeid(void)) {
value = nullptr;
}
~Test() {
//no idea how I could make this work
}
template <typename T>
T get() {
if (std::type_index(typeid(T)) == type) {
T *val_p = (T *)value;
return *val_p;
} else {
throw std::bad_typeid();
}
}
};
What I have so far works, but I don't think it would be possible to implement a destructor or copy/move constructors. The whole point is I want to store this all in a single std::unordered_map, so I can't (AFAIK) just make a template class and go from there. So, is it possible to do what I'm trying to do, and if so, how would I do it?
Based on the suggestion of GManNickG, I'm going with boost::any, as it most closely resembles what I'm looking for.
I haven't yet implemented it into the code, but the basic structure will be something along the lines of:
#include <typeinfo>
#include <boost/any.hpp>
class Statistic {
boost::any value;
public:
template <typename T>
Statistic(T val) : value(val) {}
Statistic() : value() {}
template <typename T>
bool checkType() {
return typeid(T) == value.type();
}
//Will cause an exception if the type doesn't match
//Caller should check type if unsure
template <typename T>
T get() {
if (checkType<T>()) {
return boost::any_cast<T>(value);
} else {
//throw some exception
throw bad_any_cast();
}
}
}
With this, I don't need to deal with destructors or copy/move functions, since the implicit ones will call the code already implemented by the boost library.
EDIT:
Thanks to milleniumbug for pointing out boost::any already stores the std::type_info

Return value optimization and destructor calls

I know that RVO is mostly applied but can I count on it? I have a function that creates an object of class FlagContainer.
class FlagContainer {
public:
~FlagContainer() {
someItem->flag = true;
}
private:
Item * someItem;
}
public FlagContainer createFlagContainer() {
return FlagContainer();
}
After the caller used the container, the flag must be set. So I can do this with the destructor.
{
FlagContainer container = createFlagContainer();
// do something with container
}
When out of scope, the destructor will be called. But can I be sure that the destructor will never be called in createFlagContainer? Is there any way to achieve this?
I would use AVR GCC 4.7.0 compiler.
I know that RVO is mostly applied but can I count on it?
Don't rely on RVO for logic. Put simply, someone compiling your program can switch it off with a command-line option.
Is there any way to achieve this?
Surprisingly, the standard library already gives you this functionality so you don't need to run the risk of implementing it yourself (move constructors and operators are notoriously difficult to get right)
std::unique_ptr with a custom deleter does the job nicely.
#include <iostream>
#include <memory>
#include <cassert>
// test type
struct X
{
bool flag = false;
};
// a custom deleter that sets a flag on the target
struct flag_setter_impl
{
template<class X>
void operator()(X* px) const {
if (px) {
assert(!px->flag);
std::cout << "setting flag!" << std::endl;
px->flag = true;
}
}
};
// a type of unique_ptr which does not delete, but sets a flag
template<class X>
using flag_setter = std::unique_ptr<X, flag_setter_impl>;
// make a flag_stter for x
template<class X>
auto make_flag_setter(X& x) -> flag_setter<X>
{
return flag_setter<X>(&x, flag_setter_impl());
}
// quick test
auto main() -> int
{
using namespace std;
X x;
{
auto fs1 = make_flag_setter(x);
auto fs2 = move(fs1);
}
return 0;
}
but I don't have the STL on my target
Then don't forget your rules of 0, 3, 5
#include <iostream>
#include <memory>
#include <cassert>
// test type
struct X
{
bool flag = false;
};
// a custom deleter that sets a flag on the target
struct flag_setter_impl
{
template<class X>
void operator()(X* px) const {
if (px) {
assert(!px->flag);
std::cout << "setting flag!" << std::endl;
px->flag = true;
}
}
};
// a type of unique_ptr which does not delete, but sets a flag
template<class X>
struct flag_setter
{
flag_setter(X* px) : px(px) {}
flag_setter(const flag_setter&) = delete;
flag_setter(flag_setter&& r) noexcept : px(r.px) { r.px = nullptr; }
flag_setter& operator=(const flag_setter& r) = delete;
flag_setter& operator=(flag_setter&& r)
{
flag_setter tmp(std::move(r));
std::swap(tmp.px, px);
return *this;
}
~flag_setter() noexcept {
flag_setter_impl()(px);
}
private:
X* px;
};
// make a flag_stter for x
template<class X>
auto make_flag_setter(X& x) -> flag_setter<X>
{
return flag_setter<X>(&x);
}
// quick test
auto main() -> int
{
using namespace std;
X x;
{
auto fs1 = make_flag_setter(x);
auto fs2 = move(fs1);
}
return 0;
}
There is no guarantee [yet] that copy-elision is applied. Guaranteed copy-elision is proposed for inclusion into C++17. Whether copy-elision is applied is entirely at the discretion of the compiler (some compilers have an option to entirely disable it, though).
A potential approach avoiding this need might be the use of an essentially unusable type which can be used only as the constructor argument for the type you are interested in being used and to return an object of that type:
class FlagContainerBuilder {
friend class FlagContainer;
public:
FlagContainerBuilder(/* suitable arguments go here */);
// nothing goes here
};
class FlagContainer {
// ...
public:
FlagContainer(FlagContainerBuilder&& builder);
// as before
};
FlagContainerBuilder createFlagContainer() { ... }
This way you avoid the need to potentially destroy a FlagContainer returned from createFlagContainer().
I know that RVO is mostly applied but can I count on it?
No. Compilers are allowed to implement RVO, but not required. You can only count on it, when your compiler promises to do so.
Although this particular case as per standard 12.8/3/p31.1 Copying and moving class objects [class.copy] renders as a context that the compiler can do NRVO (aka copy elision), you can't rely on it. A program that relies on this kind of optimization is effectively non portable.
To ensure move of the object I would define a move constructor and inside I would null the pointer of the other object, while in the destructor I would check whether the pointer is nullptr in order to set its flag true:
class FlagContainer {
public:
FlagContainer(FlagContainer&& other) : someItem(other.someItem) {
other.someItem = nullptr;
}
~FlagContainer() {
if(someItem) someItem->flag = true;
}
Item * someItem;
};
FlagContainer createFlagContainer() {
return FlagContainer();
}
Live Demo

Non-Static member variables creation like static singleton creation in C++

First, I really like the pattern of lazy initialization of singletons. I use it in the following way to get different kind of data with varying value types (The example is simplified):
class A
{
template<typename T>
const T& getData() const
{
static T data;
return data;
}
}
I know that the data variable is not connected to any instances of the class and that it exists until the program ends.
But what I want now, is that each instance of the class A should hold the variables in a non-static way and still there should be the flexibility of calling .getData<bool>() or with any other data type, without the need to specify each possible data type in the class definition.
Is that possible? I have not come up with an idea to implement that.
I thought of something with a container like:
template<A*, typename T>
class DataContainer
{
T data;
}
With that one can extend the code to:
class A
{
template<typename T>
const T& getData() const
{
static DataContainer<this, T> container;
return container.data;
}
}
But that does not compile.
Does anybody of you have an idea how to implement that?
Here's one idea, using Boost.any:
#include <typeinfo>
#include <type_index>
#include <unordered_map>
#include <boost/any.hpp>
struct ThingGetter
{
template <typename T>
T & get()
{
auto key = std::type_index(typeid(T));
auto it = things.find(key);
if (it == things.end())
{
it = things.emplace(key, boost::any(T())).first;
}
return boost::any_cast<T&>(*it);
}
std::unordered_map<std::type_index, boost::any> things;
};
This simple version assumes that each type can be value-initialized and creates a value-initialized value if no entry for the requested type exists. Alternative implementations could return a pointer that might be null and have a separate insertion interface.
Usage:
ThingGetter mythings;
mythings.get<bool>() = true;
mythings.get<double>() = 1.5;
return mythings.get<int>();

C++ Push Multiple Types onto Vector

Note: I know similar questions to this have been asked on SO before, but I did not find them helpful or very clear.
Second note: For the scope of this project/assignment, I'm trying to avoid third party libraries, such as Boost.
I am trying to see if there is a way I can have a single vector hold multiple types, in each of its indices. For example, say I have the following code sample:
vector<something magical to hold various types> vec;
int x = 3;
string hi = "Hello World";
MyStruct s = {3, "Hi", 4.01};
vec.push_back(x);
vec.push_back(hi);
vec.push_back(s);
I've heard vector<void*> could work, but then it gets tricky with memory allocation and then there is always the possibility that certain portions in nearby memory could be unintentionally overridden if a value inserted into a certain index is larger than expected.
In my actual application, I know what possible types may be inserted into a vector, but these types do not all derive from the same super class, and there is no guarantee that all of these types will be pushed onto the vector or in what order.
Is there a way that I can safely accomplish the objective I demonstrated in my code sample?
Thank you for your time.
The objects hold by the std::vector<T> need to be of a homogenous type. If you need to put objects of different type into one vector you need somehow erase their type and make them all look similar. You could use the moral equivalent of boost::any or boost::variant<...>. The idea of boost::any is to encapsulate a type hierarchy, storing a pointer to the base but pointing to a templatized derived. A very rough and incomplete outline looks something like this:
#include <algorithm>
#include <iostream>
class any
{
private:
struct base {
virtual ~base() {}
virtual base* clone() const = 0;
};
template <typename T>
struct data: base {
data(T const& value): value_(value) {}
base* clone() const { return new data<T>(*this); }
T value_;
};
base* ptr_;
public:
template <typename T> any(T const& value): ptr_(new data<T>(value)) {}
any(any const& other): ptr_(other.ptr_->clone()) {}
any& operator= (any const& other) {
any(other).swap(*this);
return *this;
}
~any() { delete this->ptr_; }
void swap(any& other) { std::swap(this->ptr_, other.ptr_); }
template <typename T>
T& get() {
return dynamic_cast<data<T>&>(*this->ptr_).value_;
}
};
int main()
{
any a0(17);
any a1(3.14);
try { a0.get<double>(); } catch (...) {}
a0 = a1;
std::cout << a0.get<double>() << "\n";
}
As suggested you can use various forms of unions, variants, etc. Depending on what you want to do with your stored objects, external polymorphism could do exactly what you want, if you can define all necessary operations in a base class interface.
Here's an example if all we want to do is print the objects to the console:
#include <iostream>
#include <string>
#include <vector>
#include <memory>
class any_type
{
public:
virtual ~any_type() {}
virtual void print() = 0;
};
template <class T>
class concrete_type : public any_type
{
public:
concrete_type(const T& value) : value_(value)
{}
virtual void print()
{
std::cout << value_ << '\n';
}
private:
T value_;
};
int main()
{
std::vector<std::unique_ptr<any_type>> v(2);
v[0].reset(new concrete_type<int>(99));
v[1].reset(new concrete_type<std::string>("Bottles of Beer"));
for(size_t x = 0; x < 2; ++x)
{
v[x]->print();
}
return 0;
}
In order to do that, you'll definitely need a wrapper class to somehow conceal the type information of your objects from the vector.
It's probably also good to have this class throw an exception when you try to get Type-A back when you have previously stored a Type-B into it.
Here is part of the Holder class from one of my projects. You can probably start from here.
Note: due to the use of unrestricted unions, this only works in C++11. More information about this can be found here: What are Unrestricted Unions proposed in C++11?
class Holder {
public:
enum Type {
BOOL,
INT,
STRING,
// Other types you want to store into vector.
};
template<typename T>
Holder (Type type, T val);
~Holder () {
// You want to properly destroy
// union members below that have non-trivial constructors
}
operator bool () const {
if (type_ != BOOL) {
throw SomeException();
}
return impl_.bool_;
}
// Do the same for other operators
// Or maybe use templates?
private:
union Impl {
bool bool_;
int int_;
string string_;
Impl() { new(&string_) string; }
} impl_;
Type type_;
// Other stuff.
};

boost::optional<> in a union?

I have an optional POD struct that will be contained inside a union.
boost::optional<> holds its type by value, so I thought this could work:
union helper
{
int foo;
struct
{
char basic_info;
struct details {
//...
};
boost::optional<details> extended_info;
} bar;
// ...
};
helper x = make_bar();
if( x.bar.extended_info )
{
// use x.bar.extended_info->elements
}
but VS2008 complained that my bar struct now had a copy constructor due to the boost::optional<details> element.
As a replacement, I've added a boolean flag to indicate whether the optional parameter is valid, but it's clunky:
union helper
{
int foo;
struct
{
char basic;
struct details {
bool valid;
//...
} extended;
} bar;
// ...
};
I considered implementing details::operator bool() to return the details::valid variable, but that's obscure and a disservice to humanity.
boost::optional<> clearly documents the syntax and intent and doesn't require detective work.
Finally, the helper union needs to be POD, so I can't do any dynamic allocation - otherwise I would use a pointer.
Any suggestions for something syntactically similar to boost::optional<> that's usable in a union?
You can not use non-POD types as fields in union. Use boost::variant or something like it in C++ instead of union. Leave union only for compatibility with modules written in C.
As others have mentioned, the ideal thing to do is to change from a union to a boost::variant<>.
However, if this isn't possible, you can implement a POD approximation of boost::optional<> as follows:
Implementation
template <typename T>
class Optional
{
T value;
bool valid;
public:
// for the if(var) test
operator bool() const { return valid; }
// for assigning a value
Optional<T> &operator=(T rhs)
{
value = rhs;
valid = true;
return *this;
}
// for assigning "empty"
Optional<T> &operator=(void *)
{
valid = false;
return *this;
}
// non-const accessors
T &operator*() { return value; }
T *operator->() { return &value; }
// const accessors
const T &operator*() const { return value; }
const T *operator->() const { return &value; }
};
The const accessors are necessary if you are holding a const instance of Optional<>.
Usage
Like a pointer, Optional<T> has no default state and must be initialized before you can rely on it (null or not).
Unlike boost::optional<T>, Optional<T> cannot be constructed from its T value type, and can only be constructed from another Optional<T>.
If you really want to value- or null-initialize it at construction, you could make a helper class with an operator Optional<T>(). I chose not to.
Construction
Optional<details> additional_info;
Optional<details> more_info(additional_info);
Assignment
// if there's no additional info
additional_info = 0;
// if there is extended info
details x;
// ...populate x...
additional_info = x;
Data access
if( extended_info )
{
extended_info->member;
// - or -
details &info = *extended_info;
}
So - it didn't turn out to be too bad. It doesn't make me feel quite warm and fuzzy, but it gets the job done.