I need to create a generic object carrier class. I came up with something simple like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
This works well when T has got a default constructor (parameterless). Things gets complicated when T has parameterized constructors. So I rewrote the class like
template<typename T>
class ObjectCarrier
{
public:
const T& item() const
{
return *item_;
}
void setItem(T& item)
{
item_ = new T ( item );
}
private:
T* item_;
};
Changed the item_ variable to T* and created a new instance using the copy constructor of T. Again this worked well until T is a pointer type. I mean ObjectCarrier<Foo*> won't work.
I am wondering how can I design this class so that it works for almost all kind of types. I think I may need to create a traits type specialized for pointers. But unfortunately, I am not able to make that work.
Any help would be great.
The above approaches are way way too complicated. Keep it simple, and just solve the constructor arg problem by using template constructors. Don't use pointers, they will create object lifetime and copying headaches.
Here's an implementation I use a lot. The template constructors will forward arguments for things directly on to the nested object which is convenient. The operator T& values let you pass carrier<T> to functions that take a type T, without expensive copying. You can wrap objects that take up to two arguments with this code.
/* A wrapper of type T */
template <typename T>
struct carrier {
carrier() {}
template <typename A1> carrier(const A1& a1) : value(a1) {}
template <typename A1, typename A2> carrier(const A1& a1, const A2& a2) : value(a1, a2) {}
operator T&() { return value; }
operator const T&() const { return value; }
T value;
};
You can use it like this:
const carrier<point> p1(10,10); // make p1 const to stop people changing it
showPoint(p1); // calls a function that expects a point,
showPoint(p1.value); // access the point directly
You can use template specialization for the T* type and rewrite the methods to suite pointers. You can do something like:
template<typename T>
class ObjectCarrier<T*>
{
public:
const T* item() const
{
return item_;
}
void setItem(T* item)
{
item_ = item;
}
private:
T* item_;
};
There is a design patern that is possibly relevant to this - Memento.
A bit off topic, but bear in mind that as soon as you start newing objects up inside your class, you'll need a way to manage the memory. I'd suggest using an std::auto_ptr at the least. You'll also need to provide a copy constructor and an assignment operator, when using std::auto_ptr.
It might be possible to hold the object by value and still defer its construction with the use of placement new and something like the following:
#include <iostream>
#include <cassert>
template <class T>
class ObjectCarrier
{
public:
ObjectCarrier(): ref(0) {}
ObjectCarrier(const ObjectCarrier& other): ref(0)
{
set_data(other.ref);
}
~ObjectCarrier()
{
clear();
}
const ObjectCarrier& operator = (const ObjectCarrier& other)
{
if (other.empty())
clear();
else
set_data(other.ref);
return *this;
}
void set(const T& value)
{
set_value(value);
}
const T& get() const
{
assert(!empty() && "No object being carried");
return *ref;
}
bool empty() const
{
return ref == 0;
}
void clear()
{
if (!empty()) {
ref->~T();
ref = 0;
}
}
private:
char data[sizeof(T)];
T* ref;
void set_value(const T& value)
{
if (!empty()) {
*ref = value;
}
else {
ref = new (data) T(value);
}
}
void set_data(const T* value)
{
if (value) {
set_value(*value);
}
}
};
int main()
{
ObjectCarrier<int> i;
ObjectCarrier<int> j(i);
i = j;
i.set(10);
std::cout << i.get() << '\n';
j = i;
i.set(20);
std::cout << i.get() << ' ' << j.get() << ' ' << ObjectCarrier<int>(i).get() << '\n';
}
However, I would somewhat question the usefulness of this class. Perhaps the only purpose it could have, would be to act as Boost.Optional.
But if you don't want the class to be able to not hold a value, just give it a parametrized constructor:
template<typename T>
class ObjectCarrier
{
public:
ObjectCarrier(const T& value = T()):
item_(value)
{
}
const T& item() const
{
return item_;
}
void setItem(T& item)
{
item_ = item;
}
private:
T item_;
};
(It's just that this class seems rather useless, unless perhaps as a facade for code that expects variables to have item and setItem methods, rather than, say, an assignment operator.)
boost::optional does something very similar to this (also boost::any, but nevermind).
You can check out how its implemented at: http://cplusplus.co.il/2009/12/04/boost-optional-and-its-internals/ and don't worry - it's pretty straightforward.
Related
Suppose I have a class in C++11 like this:
class Something
{
...
private:
class1* a;
class2* b;
class3* c;
public:
class1* reada() { return a; }
class2* readb() { return b; }
class3* readc() { return c; }
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
}
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
Something like this maybe?
class Something
{
...
private:
templateContainer = {class1*,class2*,class3*}
template<thing in templateContainer>
thing variableOfTypeThing;
public:
template<thing in templateContainer>
<thing> read() {return variableOfTypeThing<thing>;}
void customFunctionForclass1();
void customFunctionForclass2();
void customFunctionForclass3();
}
As you can tell from the example, I'm confused.
Basically, I have a class which acts as a container for guaranteed unique class variables (no class1 A; class1 B)
Some function groups for the class are almost identical some function groups are highly varied. It would be great for future people to only have to modify the different parts of the class and get the rest from the templates.
I thought maybe there would be a way by splitting this class up into lots of classes and stuffing them into an array of void pointers, but that seems unwise.
Suggestions?
I'd like to make the read functions templated so that if another programmer adds another member class, the corresponding read function will be template-magic created.
You could encapsulate the user defined classes in a thin wrapper class with a read() function that returns the contained instance. Adding a user defined class to Something would then be done by inheriting wrapper<user_defined_class>.
Basically, I have a class which acts as a container for guaranteed unique class variables
Inheriting this wrapper prevents you from including the same class twice so it could possibly be a way forward:
#include <iostream>
// the "thing" wrapper
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
private:
T variable;
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : thing<int>,
thing<double>,
thing<user_defined>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : thing<user_defined>(val) {}
Something() : Something("") {} // default ctor
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Edit: It doesn't fulfill the index part of your question though. You access it using the type you'd like to get() as a tag. You basically build a very rudimentary tuple I guess.
Code based on #Ted Lyngmo's answer:
#include <iostream>
#include <string>
template<typename T>
struct thing {
// forward construction arguments to the contained variable
template<class... Args>
thing(Args&&... args) : variable(std::forward<Args>(args)...) {}
// basic interface, const and non-const. I called it get() instead of read()
T const& get() const { return variable; }
T& get() { return variable; }
protected:
T variable;
};
template<typename ...Ts>
struct things : thing<Ts>... {
template<class... SubTs>
things(thing<SubTs>&&... ts) : thing<SubTs>(std::move(ts))... {}
// access via derived class, const and non-const
template<typename T>
T const& get() const {
return thing<T>::get(); // get() from the correct base
}
template<typename T>
T& get() {
return thing<T>::get(); // get() from the correct base
}
};
// a troublesome user defined class that is not default constructibe :-(
struct user_defined {
user_defined() = delete; // silly example really, but it's just to demonstrate
user_defined(const std::string& v) : str(v) {}
user_defined& operator=(const std::string& v) {
str = v;
return *this;
}
std::string const& say() const { return str; }
private:
std::string str;
};
struct non_default {
non_default() = delete;
non_default(int) {}
};
std::ostream& operator<<(std::ostream& os, const user_defined& ud) {
return os << ud.say();
}
// ... and the "Something" class that inherits the wrapped types.
class Something : public things<int, double, user_defined, non_default>
{
public:
// add initial values for types that are not default constructible
Something(const std::string& val) : things(thing<user_defined>(val), thing<non_default>(0)) {}
Something() : Something("") {} // default ctor
};
void print(const Something& s) {
// using the const interface
std::cout << s.get<int>() << "\n";
std::cout << s.get<double>() << "\n";
std::cout << s.get<user_defined>() << "\n";
}
int main() {
Something foo;
// using the non-const interface to set
foo.get<int>() = 10;
foo.get<double>() = 3.14159;
foo.get<user_defined>() = "Hello world";
print(foo);
}
Recently I tried to implement my own version of a smart pointer. The implementation looks a bit like the following:
class Var {
private:
void* value;
unsigned short* uses;
public:
Var() : value(nullptr), uses(new unsigned short(1)) { }
template<typename K>
Var(K value) : value((void*)new K(value)), uses(new unsigned short(1)) { }
Var(const Var &obj) {
value = obj.value;
(*(uses = obj.uses))++;
}
~Var() {
if (value == nullptr && uses == nullptr) return;
if (((*uses) -= 1) <= 0) {
delete value;
delete uses;
value = uses = nullptr;
}
}
Var& operator=(const Var& obj) {
if (this != &obj) {
this->~Var();
value = obj.value;
(*(uses = obj.uses))++;
}
return *this;
}
};
The implementation should be straight forward, as value holds the pointer and uses counts the references.
Please note the pointer is stored as a void* and the pointer class is not fixed to certain (generic) type.
The Problem
Most of the time the smart pointer does it's job... the exception being the following:
class C {
public:
Var var;
C(Var var) : var(var) {}
};
void test() {
std::string string = std::string("Heyo");
Var var1 = Var(string);
C c = C(var1);
Var var2 = Var(c);
}
void main() {
test();
}
When running that code the very first instance, var1, does not get deleted after test has run.
Yes, using a void* is not exactly the finest of methods. Yet lets not get off topic. The code compiles perfectly fine (if one might question my use of sub-assign operator). And if the error would be in the deletion of a void* the reference counter, uses, would be deleted but it is not.
I have checked with the destructors before and they all get called as they should.
Do also note that the programm runs without errors.
Thank You all in advance,
Sheldon
Three big problems I see with your code are:
you are storing the allocated object pointer as a void*, and then calling delete on it as-is. That will not call the object's destructor. You must type-cast the void* back to the original type before calling delete, but you can't do since you have lost the type info after the Var constructor exits.
you have separated the object pointer and the reference counter from each other. They should be kept together at all times. Best way to do that is to store them in a struct, and then allocate and pass that around as needed.
your operator= is calling this->~Var(), which is completely wrong. Once you do that, the object pointed to by this is no longer valid! You need to keep the instance alive, so simply decrement its current reference counter, freeing its stored object if needed, and then copy the pointers from the source Var and increment that reference counter.
Try this alternate implementation instead (Live Demo):
class Var
{
private:
struct controlBlockBase
{
unsigned short uses;
controlBlockBase() : uses(1) { }
virtual ~controlBlockBase() { }
};
template <class K>
struct controlBlockImpl : controlBlockBase
{
K value;
controlBlockImpl(const K &val) : controlBlockBase(), value(val) {}
};
controlBlockBase *cb;
public:
Var() : cb(nullptr) { }
template<typename K>
Var(const K &value) : cb(new controlBlockImpl<K>(value)) { }
Var(const Var &obj) : cb(obj.cb) {
if (cb) {
++(cb->uses);
}
}
Var(Var &&obj) : cb(nullptr) {
obj.swap(*this);
}
~Var() {
if ((cb) && ((cb->uses -= 1) <= 0)) {
delete cb;
cb = nullptr;
}
}
Var& operator=(const Var& obj) {
if (this != &obj) {
Var(obj).swap(*this);
}
return *this;
}
Var& operator=(Var &&obj) {
obj.swap(*this);
return *this;
}
/* or, the two above operator= codes can be
merged into a single implementation, where
the input parameter is passed by non-const
value and the compiler decides whether to use
copy or move semantics as needed:
Var& operator=(Var obj) {
obj.swap(*this);
return *this;
}
*/
void swap(Var &other)
{
std::swap(cb, other.cb);
}
unsigned short getUses() const {
return (cb) ? cb->uses : 0;
}
template<class K>
K* getAs() {
if (!cb) return nullptr;
return &(dynamic_cast<controlBlockImpl<K>&>(*cb).value);
}
};
void swap(Var &v1, Var v2) {
v1.swap(v2);
}
Update: That being said, what Var is doing is basically the same effect as using a std::any wrapped in a std::shared_ptr, so you may as well just use those instead (std::any is in C++17 and higher only, use boost::any for earlier versions):
class Var
{
private:
std::shared_ptr<std::any> ptr;
public:
template<typename K>
Var(const K &value) : ptr(std::make_shared<std::any>(value)) { }
void swap(Var &other) {
std::swap(ptr, other.ptr);
}
long getUses() const {
return ptr.use_count();
}
template<class K>
K* getAs() {
return any_cast<K>(ptr.get());
}
};
void swap(Var &v1, Var &v2) {
v1.swap(v2);
}
I'd like to implement simple database for practice, but I cant find solution for one problem. Let's we have something like:
template <class T> class simpleDB
{
public:
string pathToFile;
void writeToFile();
vector<T> base;
//setter for "base"
//getter for "base"
}
Thing I wish is to call writeToFile() after each square-bracket setter call, so the question is: "How should I write such []setter?".
There are a lot of setter examples on google but none of them avail to call something after returning reference for vector member.
Note that T supposed to be any custom complex struct, ex:
struct point
{
int x,y;
}
Thanks
UPD: as asked, I'd like to use this thing as(I skip part with allocating of first element, since its not a question):
simpleDB<point> db;
db[0].x = 1;
db[0].y = 1;
Create a proxy class with an assignment operator.
template <class T> class simpleDB {
// ...
class Proxy {
simpleDB& db;
size_t i;
Proxy& operator=(T t) {
// If you want to auto-allocate the slot...
if (db.base.size() <= i) db.base.resize(i + 1);
db.base[i] = t;
db.writeToFile();
return *this;
}
T operator*() const { return db.base.at(i); }
};
Proxy operator[](size_t i) { return {*this, i}; }
const Proxy operator[](size_t i) const { return {*this, i}; }
};
Apologies for the long title. I am trying to write an assignment operator and a copy constructor for a class which I call Store.
The purpose of Store is hold other structures (e.g. integers, floats), identified by a std::string, which can be added/retrieved from the Store. This is implemented with a std::map, with a std::string as the 'key' in the map and the particular structure as the 'value' in the map.
Store is defined as follows:
class Store {
public:
Store() {}
template <class T>
const T& get(const std::string& key) const;
template <class T>
void put(const std::string& key, const T& value, const bool& overwrite = false);
private:
std::map<std::string,FieldBase*> m_data;
};
where FieldBase is defined as follows:
class FieldBase {
public:
FieldBase() {}
virtual ~FieldBase() {}
}
and a class derived from FieldBase called Field is defined as follows:
template <class T>
class Field : public FieldBase {
public:
Field(const T& value) : m_value(value) {}
template <class U>
Field(const Field<U>& other) : m_value( U(other.m_value) ) {}
template <class U>
Field& operator=(const Field<U>& other)
{
m_value = U(other.m_value);
return *this;
}
virtual ~Field() {}
const T& get() const { return m_value ; }
private:
T m_value;
};
The functionality in Store to add and retrieve, is defined below.
To retrieve, one uses Store::get() :
template <class T>
const T& Store::get(const std::string& key) const
{
std::map<std::string,FieldBase*>::const_iterator it = m_data.find(key);
if ( it == m_data.end() ) {
std::cout << "Field with name " << key <<" doesn't exist!" << std::endl;
throw 0;
}
Field<T>* field = dynamic_cast<Field<T>*>(it->second);
if ( field == 0 ) {
std::cout << "Field with name " << key << " doesn't have correct type!" << std::endl;
throw 0;
}
return field->get();
}
and to add, one uses Store::put()
template <class T>
void Store::put(const std::string& key, const T& value, const bool& overwrite)
{
std::map<std::string,FieldBase*>::iterator it = m_data.find(key);
if ( it != m_data.end() ) {
if ( ! overwrite ) {
std::cout << "Field with name " << key << " doesn't exist!" << std::endl;
throw 0;
}
else {
delete it->second;
it->second = 0;
}
}
Field<T>* field = new Field<T>(value);
m_data[key] = field;
}
So, having described the classes and their interactions, I finally arrive at the question:
How should the copy constructor and assignment operator look for Store?
Obviously, one should iterate over the std::map<std::string,FieldBase*> and somehow fill the target map by deep copying the objects, but my problem is that I don't know how to determine the type of the Field which hides beneath each FieldBase pointer...
// How should these be implemented ???
Store::Store(const Store& other);
Store& Store::operator=(const Store& other);
Any help is much appreciated.
You should look at the clone pattern.
http://en.wikipedia.org/wiki/Cloning_(programming)
What you do is add a pure abstract member function to FieldBase which is defined in the most derived types (Field).
So:
virtual FieldBase* clone() const = 0; //! This goes in FieldBase
FieldBase* clone() const { return new Field<T>(m_value); } //! This goes in Field
Then in the copy constructor you iterate over the map and clone the underlying values before inserting them in the new instance's map.
Something like this:
Store(const Store& other)
{
typedef std::map<std::string, FieldBase*> StoreMap;
for (StoreMap::const_iterator it(other.m_data.begin()); it != other.m_data.end(); ++it)
m_data.insert(std::make_pair(it->first, it->second->clone()));
}
To implement a deep copy you can add an abstract function virtual FieldBase * FieldBase::clone() = 0;
The implementation FieldBase* Field<T>::clone() would then return new Field<T>(*this);
The only thing left is to iterate over each entry of Store::m_data and call it->second->clone();
Here is the deal:
I have a templated class C
template<class T>
class C;
that has a member that is basically a pointer to a reinterpretation of T called P (don't worry about P)
P* reint;
what I want to do is a method that receives a T and copies it into reint
void foo (T& param) {
new (reint) (param);
}
problem is the compiler is giving out warnings that reint is not a T that I want to get rid of. My first idea was to reinterpret reint into a T:
void foo (T& param) {
new (reinterpret_cast<T&>(*reint)) T(param);
}
but the compiler started giving me an error saying
invalid conversion from const void* to void*
So i looked it up and new is defined as such:
void* operator new (std::size_t size, void* ptr) throw();
So for some reason my casting is turning reint into a const void*.
New idea: cast reint to a T and call the copy constructor. Problem: no clue how to call the copy constructor from an unknown class.
(maybe
reinterpret_cast<T>(*reint).T(param);
?)
Could you help me please?
Maybe you want something like:
#include <stdexcept>
struct Data
{
const std::string value;
Data(const std::string& value)
: value(value)
{}
Data(const Data& other) = default;
Data& operator = (const Data& other) = delete;
};
template <typename T>
class Holder
{
public:
Holder() = default;
Holder(const T& data) {
assign(data);
}
~Holder() {
release();
}
void assign(const T& data) {
release();
new (m_data) T(data);
m_valid = true;
}
void release() {
if(m_valid) {
reinterpret_cast<T*>(m_data)->~T();
m_valid = false;
}
}
const T& get() const {
if( ! m_valid) throw std::runtime_error("Invalid");
return *reinterpret_cast<const T*>(m_data);
}
private:
bool m_valid = false;
char m_data[sizeof(T)];
};
#include <iostream>
int main() {
Holder<Data> holder;
holder.assign(Data("Hello"));
const Data& data = holder.get();
std::cout << data.value << '\n';
}
You're going the wrong way, you want somethng more like:
reint = reinterpret_cast<P*>(param);
The solution was to make a struct to return the reinterpreted P for both const and unconst
template <class T> struct Temp {
T* switch (P* r) { return reinterpret_cast<T*>(r); }
}
template <class T> struct Temp <const T> {
T* switch (P* r) { return reinterpret_cast<T*>(r); }
}
then use the struct to remove const from reint
new (Temp::switch(reint)) T(param);