Anonymous union/structure holding a generic vector - c++

I'm trying to create an anonymous union that holds a generic vector in order to use it as a member in a class without naming the type_name of the union itself.
So that I could call the vector inside the class as following:
vec.size();
But my approach
template <typename T>
union{
std::vector<T> vec;
};
will only give me the error "template class without a name". This also happens with structures. So does it not like to be anonymous when it is generic?
Search results just gave me the option to create a generic vector inside a named structure but, besides I couldn't get this to work either, I would loose the benefits of the anonymous union und I would need to call the vector e.g. as
struct_name.vec.size();
or even
class_name.struct_name.vec.size();
which I tried to avoid.
I want to make the vector generic so that it can store integers or doubles and I don't need to declare two different vectors with their own specific data types. Beside learning some principles of generics I also aim for lesser declarations and storage usage with this technique.

You cannot reliably do what you want. You need at least some way to discriminate at runtime if you have a vector of int or a vector of float.
With C++11 you might code
class StrangeVector {
bool has_int;
union {
std::vector<int> vint;
std::vector<float> vfloat;
};
public:
StrangeVector(bool withints) : has_int(withints) {
if (withints) new(&vint) std::vector<int>();
else new(&vfloat) std::vector<float>();
}
~StrangeVector() {
if (has_int) vint.~vector<int>();
else vfloat.~vector<float>();
}
};
But such code is really bad smelling. (I would suggest using a union of pointers, perhaps of smart pointers e.g. std::shared_ptr or std::unique_ptr, or perhaps std::optional; see this).
See also this, or boost::any ...
Notice that except for RTTI typing information is used at compile time in C++.

Related

Scoped enum and std::get

I want to use a scoped enum with a std::get to access an object stored in a std::vector
From Effective Modern C++ I'm using a version of Item 10 to cast the enum type to the underlying_type_t that can be used with std::get
template<typename E>
constexpr auto to_mytype(E enumerator) noexcept
{
return static_cast<std::underlying_type_t<E>>(enumerator);
}
and
enum class my_type{sel_1, sel_2};
I have
std::vector<std::variant<std::unique_ptr<option1>, std::unique_ptr<option2>> my_store;
which is a member of my_class and I want to use the object stored in this vector like so
void my_class::my_function(const my_type selection)
{
std::get<to_mytype(selection)>(my_store[i])->do_work();
}
where selection would be sel_1 or sel_2. If I try this I get
error: selection is not a constant expression
Really I would like to store the type selected within the class and have the user only pass it once, to the constructor of my_class
to select whether an option1 or option2 object to be added to the vector.
Is there a way I can use an enum like this? I feel like I'm missing something quite simple.
There are multiple issues with this code.
You try to use runtime index into std::get that requires compile
time index
You are trying to select in std::variant, while variant does not hold multiple types at once(tuple does). Also note that variant already knows what type it currently holds.
As a bonus problem: IMAO tuple should be rarely used since it is quite ugly from readability perspective, struct with named members is usually much nicer.

Extending a type in C++

Sadly, UFCS did not make it into C++17 and that left me with a recurring problem:
Sometimes I want to give types extra functionality using the method call syntax (without writing global functions). That would especially come handy when dealing with monads.
I see two options: One is inheritance, and the other is encapsulation. Because you cannot safely inherit from STL containers, that leaves encapsulation. For example, I want to extend std::optional, so I write:
template <typename T>
struct myoption {
// Some functionality
private:
std::optional<T> impl;
};
My problem is that every time I want to do this, I basically have to write all the constructors (and needed methods that you can use with the original type, like push_back for vectors) the original type has. Even a simpler container, like optional has 9 constructors. When using inheritance, I can simply 'inherit' the methods and constructors of a super-class. Is there a way to make this easier using encapsulation?
I would implement it by using private inheritance:
#define MAKE_PUBLIC(method) using std::vector<T>::method
template <typename T>
struct My_vector : private std::vector<T> {
MAKE_PUBLIC(push_back);
MAKE_PUBLIC(pop_back);
};
int main() {
My_vector<int> v;
v.push_back(3);
std::vector<int>* vec = new My_vector<int>; // won't compile
}
This way, you can make sure that you cannot create objects with dynamic type of My_vector and reduce the effort to make inherited methods accessible by a mere macro (or using directive) instead of creating forward functions for each member function and overload.

Storing data of different types c++

I am working on a modular data logger that allows one to log data of different types. At the moment I made a File class that is a template. In order to declare an object of such a class one would do as such: File<double> f("filename.txt") or File<float> f("filename.txt"). I want to be able to store objects that were declared with double or float as template parameters in one vector. Is it possible to do something like that? I have tried a method online that uses a union as such:
union typ {
int int_dat;
double double_dat;
float float_dat;
}
and allows me to declare a vector as such: vector<File<typ> >. However, this gives me linker errors. Is there a easier, cleaner way to attempt this? The entire project in question is here
EDIT: follow up to this. How would one circumvent the issue surrounding the fact that if I conduct such operations:
std::vector<File<typ> > files;
File<typ> f("test.txt");
files.push_back(f);
files.at(0) << 35.4;
it causes a compile time error which I comprehended as what I'm guessing is: 35.4 is not of the type typ and cannot be used in the operation <<. How would one bypass such an error?
I think your vector of unions might have some issues. I haven't looked at your full code, but refer to this:
Questions about vector, union, and pointers in C++
The following should work (see http://codepad.org/TyrURyar)
#include <vector>
union type {
int int_dat;
double double_dat;
float float_dat;
};
template <typename T>
class Foo {
T t;
};
void foo2() {
std::vector<Foo<type> > x;
// NOTE: In pre-C++11, space is required between the >'s
}
Use Boost::Variant, if you can. It's a cleaner option. Unions can be used, but you should write and read from the same member if you don't want to end up with undefined behaviour i.e. it involves book keeping, which anyways Variant does for you automatically.

container of unrelated T in c++

If I have the following hypothetical class:
namespace System
{
template <class T>
class Container
{
public:
Container() { }
~Container() { }
}
}
If I instantiate two Containers with different T's, say:
Container<int> a;
Container<string> b;
I would like to create vector with pointers to a and b. Since a and b are different types, normally this wouldn't be possible. However, if I did something like:
std::stack<void*> _collection;
void *p = reinterpret_cast<void*>(&a);
void *q = reinterpret_cast<void*>(&b);
_collection.push(a);
_collection.push(b);
Then later on, I can get a and b back from _collection like so:
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
My question is, is this the best way for storing a collection of unrelated types? Also would this be the preferred way of storing and retrieving the pointers from the vector (the reinterpret cast)? I've looked around and seen that boost has a nicer way of solving this, Boost::Any, but since this is a learning project I am on I would like to do it myself (Also I have been curious to find a good reason to use a reinterpret_cast correctly).
Consider boost::any or boost::variant if you want to store objects of heterogeneous types.
And before deciding which one to use, have a look at the comparison:
Boost.Variant vs. Boost.Any
Hopefully, it will help you to make the correct decision. Choose one, and any of the container from the standard library to store the objects, std::stack<boost::any>, std::stack<boost::variant>, or any other. Don't write your own container.
I repeat don't write your own container. Use containers from the standard library. They're well-tested.
While it is possible to cast to void * and back, the problem is knowing which type you're popping. After all, you give the example:
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
However, if you were to accidentally do:
Container<int> a = *reinterpret_cast<Container<int>*>(_collection.pop());
Container<string> b = *reinterpret_cast<Container<string>*>(_collection.pop());
Now you've got pointers to the wrong type, and will likely see crashes - or worse.
If you want to do something like this, at least use dynamic_cast to check that you have the right types. With dynamic_cast, you can have C++ check, at runtime (using RTTI), that your cast is safe, as long as the types being casted (both before and after) have a common base type with at least one virtual method.
So, first create a common base type with a virtual destructor:
class ContainerBase {
public:
virtual ~ContainerBase() { }
};
Make your containers derive from it:
template <typename T>
class Container : public ContainerBase {
// ...
}
Now use a std::stack<ContainerBase *>. When you retrieve items from the stack, use dynamic_cast<Container<int> >(stack.pop()) or dynamic_cast<Container<string> >(stack.pop()); if you have the types wrong, these will check, and will return NULL.
That said, heterogeneous containers are almost always the wrong thing to be using; at some level you need to know what's in the container so you can actually use it. What are you actually trying to accomplish by creating a container like this?

Iterating through collection of different types in C++

Situation
I have a template class TIppImage<T> for image of type T. I have singleton class CIppMemoryManager which can store a number of images of different size and type.
class CIppMemoryManager
{
public:
/// ... Singleton interface ...
template<class T> TIppImage<T>* GetImage(width, height);
private:
CIppMemoryManager();
~CIppMemoryManager();
std::map<IppDataType, void*> m_Containers;
};
IppDataType is enum, which values correspond to actual types. All management is done in template class TIppImageContainer<T>. And all specialization of this class is stored in m_Containers as a void*. It's not very good, but it is at least simple.
With this approach, I can simply implement template GetImage method like this:
template<class T> TIppImage<T>* CIppMemoryManager::GetImage(width, height)
{
return reinterpret_cast<TIppImageContainer<T>*>(m_Containers[
TIppTypeTraits<T>::ipp_data_type])->GetImage(width, height);
}
where I'm using traits class TIppTypeTraits<T> to obtain enum value from given type.
Problem
I cannot simply implement non-template methods like constructor. I need to explicitly handle all possible types:
CIppMemoryManager::CIppMemoryManager()
{
m_Containers[ipp8u] = new CIppImageContainer<Ipp8u>;
m_Containers[ipp8s] = new CIppImageContainer<Ipp8s>;
m_Containers[ipp16u] = new CIppImageContainer<Ipp16u>;
m_Containers[ipp16s] = new CIppImageContainer<Ipp16s>;
...
}
Worse, for destructor I also need to deal with void*:
CIppMemoryManager::~CIppMemoryManager()
{
delete reinterpret_cast<TIppImageContainer<Ipp8u>*>(m_Containers[ipp8u]);
delete reinterpret_cast<TIppImageContainer<Ipp8s>*>(m_Containers[ipp8s]);
delete reinterpret_cast<TIppImageContainer<Ipp16u>*>(m_Containers[ipp16u]);
delete reinterpret_cast<TIppImageContainer<Ipp16s>*>(m_Containers[ipp16s]);
...
}
So, the questions are:
a) Is there some way to iterate through collection of different types? Cannot use traits class here since function is non-template.
b) Is there some better way to store collection of containers - objects of different type? When they are just a different specialization of common template class, containers itself are pretty simple.
I think the class variant from the boost library (boost::variant) may help you. You can use visitors to execute the appropriate code depending on the type stored in a variant. A std::vector<boost::variant<T0, T1,...>> can store a list of objects of different types.
As your objects are similar, they may have the same size in memory, which is a good thing since boost::variant storage is stack-based (no heap allocation - this is faster).
What's wrong with polymorphic CIppImageContainer<T> (make them all share a common base class) and a smart pointer ?
Or some kind of boost::variant ?
boost::mpl::for_each is tailor-made for that job. Define a vector of types to operate on, a functor or lambda expression to do something, and you are done.
boost::variant is the most likely candidate but sometimes variantS become rather large as they require some extra storage and also have to deal with alignment. So maybe boost::any has advantages in some situations as well:
std::vector<std::pair< Type, boost::any > > data;
To comfortably iterate over such a container is harder (boost::transform_iterator cannot have more than one return type, so this wont work without some template trickery).