Create a smart-pointer-to-base-class from a reference - c++

I have a container which store a vector of smart-pointer-to-base-class, and I'd like to populate it via a method without requiring my users to also create that smart pointer:
class Base {
// ...
};
class Derived: public Base {
// ...
};
class Collection {
private:
vector<unique_ptr<Base>> pointers;
public:
void add(Base&& value) // #1
{
pointers.push_back(????);
}
void add<typename T>(T&& value) // #2
{
pointers.push_back(????);
}
};
int main() {
Collection collection;
collection.add(Derived("Data")); // #3
}
What's the correct way to do this, if at all? It's clear that I could use make_unique and emplacement, except that I'm concerned that the derived content won't be moved correctly.
It's possible I've spent too much time in Rust land, where moves of this kind are pretty commonplace, so let me know if I'm way off base here. Ideally, the interface looks like my #3 point up there, where the function can be called with a literal of the derived type without any extra boilerplate related to allocation or anything. I'd be find if the solution ends up being to make Collection::add generic.

You should probably stick to the template, yes. You then get
class Collection {
std::vector<std::unique_ptr<Base>> pointers;
public:
template<typename T>
void add(T &&value) {
pointers.emplace_back(std::make_unique<std::remove_reference_t<T>>(std::forward<T>(value)));
}
};
int main() {
Collection c;
Derived d;
c.add(d); // works with lvalues (copying)
c.add(std::move(d)); // or rvalues (moving)
Base b;
c.add(b);
c.add(std::move(b));
}
However, it might be more useful to provide an "emplace", which constructs an object out of arbitrary arguments (as provided by all the standard containers)
class Collection {
std::vector<std::unique_ptr<Base>> pointers;
public:
template<typename T, typename... Ts>
void emplace(Ts&&... args) {
pointers.emplace_back(std::make_unique<T>(std::forward<Ts>(args)...));
}
template<typename T> // still useful for conciseness (don't have to specify T)
void add(T &&value) {
this->emplace<std::remove_reference_t<T>>(std::forward<T>(value));
}
};
So you can further do
int main() {
Collection c;
Derived d;
c.add(d); // works with lvalues
c.add(std::move(d)); // or rvalues
c.emplace<Derived>(); // or can give arguments directly (assuming a default constructor, in this case)
Base b;
c.add(b);
c.add(std::move(b));
c.emplace<Base>();
}
A complete example on Godbolt.

Related

Is it possible to cast from vector parent* to vector child* in a function without using templates

While working on a data import system I decided to store a lot of objects deriving from one class in a vector of pointers to the parent class. And then I would like to have a function that returns a vector of any type of child pointers (using paramaters that let me know what kind of child it is).
I managed to realize a similar and simplified code here, but it uses templates and casts and I feel like only casts could be enough. However the compiler does not want to do any cast from vector A* to vector B*.
EDIT: In the real code there are many child classes, not only B, so replacing the template by B is not an option, sorry for not being precise enough.
#include <vector>
using namespace std;
class A
{
public:
int attr;
A(): attr(1) {}
};
class B : public A
{
public:
B(): A() {attr = 2;}
};
template <typename O>
vector<O*> bees(vector<A*> vecA)
{
auto vecO = vector<O*>();
for (auto it = vecA.begin(); it != vecA.end(); it++)
{
if ((*it)->attr == 2)
{
vecO.push_back(reinterpret_cast<O*>(*it));
}
}
return vecO;
}
int main()
{
auto vecA = vector<A*>();
vecA.push_back(new A());
vecA.push_back(new B());
vecA.push_back(new B());
vector<B*> vecB = bees<B>(vecA);
}
So my question is : Is it possible to have a code do the same effect without using templates ? And if not does the compiler generate specific code with this one ? Knowing there would be theorically no difference in runtime no matter the template.
Thank you.
Since you want a function that can return vector of any type of child pointer so i believe template is needed to specify child type but certain things like reinterpret_cast etc. is not needed and here is sample implementation :
class A
{
public:
int attr;
A(): attr(1) {}
virtual ~A() {};
};
class B : public A
{
public:
B(): A() {attr = 2;}
};
template<typename T>
vector<T*> bees(const vector<A*> &vecA)
{
vector<T*> vec;
for (auto it = vecA.begin(); it != vecA.end(); it++)
{
T* ptr = dynamic_cast<T*>(*it);
if(ptr != nullptr)
{
vec.push_back(*it);
}
}
return vec;
}
We are using dynamic_cast because we are downcasting parent type to child type.Also for dynamic_cast to work we need virtual destructor/virtual function as it require RTTI
Inheritance and polymorphy are supposed to hide away different child types, so the rest of your code doesn't have to worry about specific types.
Casting objects to specific types is very likely not the right approach to whatever you're trying to do. Let the types decide how they are used and what they do, not the outside world.
If you want to filter a vector to get only objects with specific properties, you shouldn't look at their types, you should ask them if they have the properties you are looking for:
void FilterA(const std::vector<A>& source, std::vector<A>& destination, std::function<bool(const A&)> filter) {
std::copy_if(source.begin(), source.end(), std::back_inserter(destination), filter);
}
Then you can call it like this:
std::vector<A> filteredVecA;
FilterA(vecA, filteredVecA, [](const A& a){return a.HasSomePropertyYouCareAbout();});
You should consider moving the type checking inside the hierarchy (this uses templates, but no casts):
class A {
public:
virtual ~A(); // you _are_ in a hierarchy of objects
template<typename T>
virtual T* as() const { return nullptr; }
};
template<typename X>
class Convertible: public A {
template<typename T>
virtual T* as() const {
if constexpr(std::is_same_v<X, T>)
return this;
else
return nullptr;
}
};
class B: public Convertible<B> {
};
template <typename O>
vector<O*> bees(vector<A*> vecA)
{
auto vecO = vector<O*>();
foreach (auto ptr: vecA)
{
auto ptrO = ptr->as<O>();
if (ptrO)
vecO.push_back(ptrO);
}
return vecO;
}
Some points:
OP's comment:
I am using reinterpret cast because it I do not cast it just doesn't compile, and it feels to me like it is the most adequate here knowing I do not need to do any changes on the object.
dynamic_cast is usually a symptom of an insufficiently designed class hierarchy. Whenever you think "I can solve this with dynamic_cast" consider adding code to your class hierarchy instead.

How to store templated objects of different type in container?

Assuming I have a vector (or list or whatever container might be more suitable here) that I would like to store multiple objects (or pointers) of a templated type in:
std::vector<MyClass<double>> v;
// std::vector<MyClass<double> *> v;
Unfortunately, I want to store different templated objects in this container (and I need to access them ideally at constant time).
My first intuition was to create some sort of WrapperClass around MyClass that would internally manage any MyClass as a member variable, but it's not clear to me how I could pass along the appropriate type through to MyClass:
#include <iostream>
#include <string>
#include <stdlib.h>
#include <vector>
using namespace std;
template<typename T>
class MyClass
{
public:
MyClass() {}
~MyClass() {}
};
// templating this of course works, but it doesn't solve my problem
template<typename T>
class WrapperClass
{
public:
WrapperClass()
{
m_object = MyClass<T>();
}
~WrapperClass() { }
private:
MyClass<T> m_object;
};
int main()
{
WrapperClass<bool> tmp = WrapperClass<bool>();
std::vector<WrapperClass<bool> *> v;
return 0;
}
So is there (A) a different container than vector that I could be using for this problem or (B) a way to select the type of MyClass in WrapperClass inside the constructor? I was thinking of something along the lines of:
class WrapperClass2
{
public:
WrapperClass2(unsigned int typeId)
{
switch (typeId)
{
case 0: m_object = new MyClass<bool>();
case 1: m_object = new MyClass<int>();
case 2: m_object = new MyClass<float>();
default: m_object = new MyClass<double>();
}
}
~WrapperClass2()
{
delete m_object;
}
private:
MyClass * m_object;
};
Another idea may be to have some parent AbstractType that I would be using in the vector, but I'm not sure how that would help with the templated type problem.
Different instantiations of a class template are completely unrelated types, so you cannot have a container that directly stores them.
You have a few options:
Keep a collection of pointers to some base class that your class template inherits from:
class Base
{
virtual ~Base {}
virtual void someMethod() const = 0;
};
template <typename T>
class MyClass : public Base
{
void someMethod() const
{
// stuff
}
};
int main()
{
std::vector<std::unique_ptr<Base>> objs;
objs.push_back(std::make_unique<MyClass<int>>());
objs.push_back(std::make_unique<MyClass<std::string>>());
for (auto& i : objs) {
i->someMethod();
}
}
This is a fairly simple approach, but it incurs a bit of runtime overhead with dynamic allocation and RTTI. Note also that someMethod can't return T, since it's a method on a parent class that doesn't know what T is.
Use some sort of type-erased wrapper like boost::any (or the forthcoming std::any in C++17).
#include <any>
#include <string>
#include <vector>
template <typename T>
class MyClass {
public:
T someMethod() const {
// stuff
return {};
}
};
void someFunctionThatTakesInt(int i) {}
void someFunctionThatTakesString(std::string s) {}
int main() {
std::vector<std::any> objs;
objs.push_back(MyClass<int>());
objs.push_back(MyClass<std::string>());
for (const auto& i : objs) {
if (i.type() == typeid(MyClass<int>)) {
auto& mc = std::any_cast<const MyClass<int>&>(i);
someFunctionThatTakesInt(mc.someMethod());
} else if (i.type() == typeid(MyClass<std::string>)) {
auto& mc = std::any_cast<const MyClass<std::string>&>(i);
someFunctionThatTakesString(mc.someMethod());
}
}
}
This approach means that you can have someMethod return T, but makes it much harder to handle retrieving objects from the vector because you have to figure out what type they are before you can do anything with them (you're essentially rolling your own RTTI).
Don't.
Rethink why you need this in the first place. Maybe another approach could work better. Maybe something with callbacks or visitors. I don't know your objective here, so I can't really say what's appropriate.
Can you do a base class and have all other classes inherit from the base class.
And you can make a list that holds a list of base class elements.
Now this is more of a pseudo example, but I hope this way would solve your problem.
Example:
class Base:
{
}
class whatever:Base
{
}
class whatever2:Base
int main()
{
list<whatever> object1;
list<whatever2> object2;
list<list<Base>> mainObj;
mainObj.push_back(object1);
mainObj.push_back(object2);
}
Now if the problem is to just have different datatypes than abstract datatypes in some container. Can't you have a Singly Link List, and have your Node generic.
Example:
template<typenameT>
struct Node
{
T data;
Node* next;
}
class LinkList
{
//Your code:
}

Is it a good idea to use variadic templates to create a safer way to pass new objects

Lets say I have a class that has a data member that is a pointer to an abstract class Foo. One of the class's setters, setFoo asks for pointer to one of Foo's subclasses. What the programmer is supposed to pass is a new object of the subclass like setFoo(new FooBar(5, 10)); So that FooContainer is the only one holding a reference to the object and is the only one responsible for deleting that object. An example would be like...
class FooContainer final {
public:
FooContainer() : currentFoo(nullptr) {}
~FooContainer() {
delete currentFoo;
}
//Setter
void setFoo(Foo *foo) {
if (currentFoo != nullptr)
delete currentFoo;
currentFoo = foo;
}
//test that it holds the class
void fireFoo() {
currentFoo->func();
}
private:
Foo* currentFoo;
};
This has some big pitfalls like if I do these.
int main() {
FooContainer fc1;
holder.setFoo(nullptr); //Error passing a null pointer
holder.fireFoo();
//---
FooContainer fc2;
Foo* fooBar = new FooBar(5, 10);
holder.setFoo(fooBar); //Error now two objects hold references to fooBar
holder.fireFoo();
delete fooBar; //Error
return 0;
}
The solution I came up with was to use a variadic template function to set foo where it's passed the foo subclass type and varargs to construct whatever the new Foo subclass is, like this.
template <typename T, typename... Args>
void setFoo(Args... args) {
currentFoo = new T(std::forward<Args>(args)...);
};
So now I can do setFoo<FooBar>(5, 5); which insures that currentFoo is not a null pointer and the FooContainer is the only reference holder. Is this be the correct way to go about this? I've never encountered a problem like this before, and If I'm getting something wrong I can always fall back to unique pointers.
For ownership, you should use one smart pointer
Then you may use setter (which allows easily to have polymorphic Foo):
class FooContainer final {
public:
void setFoo(std::unique_ptr<Foo> foo) { // may be empty
currentFoo = std::move(foo);
}
void fireFoo() {
// may be empty if not set (constructor doesn't feed it) or set with nullptr
if (currentFoo) {
currentFoo->func();
}
}
private:
std::unique_ptr<Foo> currentFoo;
};
or internal factory (which ensures that you always have value)
class FooContainer final {
public:
template <typename...Ts>
explicit FooContainer(Ts&&... args) {
currentFoo = std::make_unique<Foo>(std::forward<Ts>(args));
}
template <typename...Ts>
void createFoo(Ts&&... args) {
currentFoo = std::make_unique<Foo>(std::forward<Ts>(args));
}
void fireFoo() {
assert(currentFoo); // Cannot be nullptr (except after moved currently ;) )
currentFoo->func();
}
private:
// You may even use `Foo currentFoo;` (which some changes above) if relevant
// (think about copy/move)
std::unique_ptr<Foo> currentFoo;
};

Storing multiple types into the same container [duplicate]

This question already has answers here:
Heterogeneous containers in C++
(7 answers)
Closed 8 years ago.
Introduction
Say I have the follow
class thing {
template<typename T> void method(T value) {}
}
What I want to do is to store whatever value is passed into value no matter what type into a std::vector or something and without turning this into a template class (because that doesn't solve my problem in anyway)
I want to be able to do this without using boost (as much i love boost i am not going to use it all the time)
Attempted Ideas
Void Pointer
My initial though is to use a void* however i would lose the type of the object and it could end up being unsafe.
Union/Struct
My next thought was to use a union/struct like the one below:
union type_wrapper {
int a;
char f;
/* etc, etc, etc */
}
However i would run into the same problem as I would have to track the type, so i make sure it remains the same when ever used.
Wrapper Class
Then next thing i attempted was a class that would return the type in a function call like so:
template<typename T>
class type_wrapper {
T getType() { return /* get value of type/pointer/object here */ }
/*Stored in some manner */
}
Problem with is the same thing as with just the type on its own in that it cannot be stored in a list called lets say std::list<AClass> when its of type std::list<BClass> or std::list<int> etc
Other thing
All other examples i have looked at have do what i am doing but are expect that you track the type of the object one way or another, or use boost.
tl;dr
What could i try doing so that i could pass a parameter of type int and storing into a std::list etc it while using the same template function to pass a parameter of type 'cheese' (an imaginary class dedicated to filling your programs with cheese) and storing it into the same list, etc
I don't know if this will solve your problem, but you can use some polymorphic type for the container, and encapsulate the object in a generic derived class, so calls to object's member functions from the derived class' member functions can have full type information (they will be specialized templates), but your "thing" won't be generic, and client code won't care (or even know) about this inhertance:
class Aux {
public:
virtual void DoSomething() =0 ;
};
template<typename T>
class AuxTemp : public Aux {
T *real_obj;
public:
AuxTemp(const T &obj) : real_obj(new T(obj)) {} // create
AuxTemp(const AuxTemp &other) : real_obj(new T(*other.real_obj)) { } // copy
AuxTemp(AuxTemp &&other) : real_obj(other.real_obj) { other.real_obj=nullptr; } // move
~AuxTemp() { delete real_obj; } // destroy
void DoSomething() override {
real_obj->DoSomething(); // here we call the method with full type information for real_obj
}
};
class Thing {
std::vector<Aux*> v;
public:
template<typename T> void Add(const T &value) {
v.push_back(new AuxTemp<T>(value));
}
void DoSomethingForAll() {
for(auto &x:v) x->DoSomething();
}
};
Yo can test this with:
class A {
public:
void DoSomething() { std::cout << "A"<< std::endl; }
};
class B {
public:
void DoSomething() { std::cout << "B"<< std::endl; }
};
int main(int argc, char *argv[]) {
Thing t;
t.Add(A{});
t.Add(B{});
t.DoSomethingForAll();
return 0;
}
For each new type you push to your vector, a new derived and specialized wrapper class is made by Add member function, so virtual table can handle calls to DoSomething in order to use the proper and full-aware-of-real-type version.
I think what I propose is a bizarre implementation "type-erasure" (you should google for this term to find more elaborated solutions).

how to implement common functor for several classes in c++

suppose you have two (or more) classes with private member vectors:
class A {
private:
std::vector<X> priv_vec;
public:
//more stuff
}
class B {
private:
std::vector<Y> priv_vec;
public:
//more stuff
}
and you have a functor-class which has a state and works on a generic vector (does sorting or counts elements or something like that). The state of the functor is initialized by the first vector the functor is working on. If the functor is applied to another vector later, it will change its behavior depending on the state (sorts in the same way or trims the second vector after as many elements as the first one, etc)
What is the best way to implement such a functor (desgin-pattern or functional interface?) without exposing the private vectors to the other classes or the user of the classes?
for example:
The user would like to initialize this functor with an object of class A and then use this initialized functor for one or more objects of class B. The user isn't able (and shouldn't be) to use the private vectors directly as function-arguments for the functor.
Hum, first, beware on states in functors.
Most STL implementation of the algorithms may copy your functors around, therefore you generally have to extract the state in an outer structure.
Now, for the application of functors, well it is simple: have your classes declare a template member function!
class A
{
public:
template <class Functor>
Functor Apply(Functor f);
private:
};
class B
{
public:
template <class Functor>
Functor Apply(Functor f);
};
// Usage
MyFunctor f;
A a;
B b;
b.Apply(a.Apply(f));
As for the functor, if you need state:
// Alternative 1
class FunctorState {};
class Functor
{
public:
Functor(FunctorState& state): m_state(state) {}
// some operator()(...)
private:
FunctorState& m_state;
};
// Alternative 2
class Functor
{
struct FunctorState {};
public:
Functor(): m_state(new FunctorState) {}
// some operator()(...)
private:
boost::shared_ptr<FunctorState> m_state;
};
This way, copies of the Functor all points to the same FunctorState instance. Just choose depending if you wish to actually access the state from outside the class or not.
Looks like a problem of importing policies from an object of class A and applying them to objects of class B, the only difference being, all of this is done at runtime (as opposed to typical policy-based design). This begs the question, are these policies proprietary to class A or can we isolate them and pass them around as required? That ought to simplify the deisgn.
A solution based on templates.
#include <iostream>
#include <string>
#include <vector>
// Wraps up a vector of type T and exposes a
// simple interface to access it.
template <class T>
class A
{
public:
A(const std::vector<T>& v) : priv_vec(v) { }
virtual size_t count() const { return priv_vec.size(); }
virtual T operator[](size_t index) const { return priv_vec[index]; }
private:
std::vector<T> priv_vec;
};
// A sample functor with state.
// The state is the size and current index of the vector object.
class Functor
{
public:
Functor() : _size(0), _index(0) { }
// Prints the element at the current index.
// If the index exceeds size, it is reset to 0.
template <class T>
void operator()(const A<T>& b)
{
if (_size == 0) _size = b.count();
if (_index >= _size) _index = 0;
std::cout << b[_index++] << '\n';
}
private:
size_t _size;
size_t _index;
};
int
main()
{
// Some tests.
std::vector<int> int_vec;
int_vec.push_back(1);
int_vec.push_back(2);
int_vec.push_back(3);
A<int> a(int_vec);
std::vector<std::string> str_vec;
str_vec.push_back("aaaa");
str_vec.push_back("bbbb");
str_vec.push_back("cccc");
A<std::string> b(str_vec);
Functor f;
f(a); // 1
f(b); // bbbb
f(a); // 3
f(a); // 1
f(a); // 2
f(b); // cccc
return 0;
}