C++ explicit copy constructor? - c++

I've hit a wall concerning this explicit copy constructor issue. I've been writing a class to figure things out:
#include <iostream>
template<class T>
class Mat
{
private:
T data;
public:
void set(T value)
{
data = value;
}
Mat()
: data(T(0))
{
}
explicit Mat(const Mat& another)
{
*this = another;
}
Mat& operator=(const Mat& another)
{
data = another.data;
return *this;
}
template<class U>
explicit operator Mat<U>()
{
Mat<U> result;
result.set(static_cast<U>(data));
return result;
}
void print()
{
std::cout << data << std::endl;
}
};
int main()
{
Mat< double > d1;
d1.set(3.14159);
Mat< int > i1(static_cast<Mat<int>>(d1));
d1.print();
i1.print();
std::cin.sync();
std::cin.ignore();
return 0;
}
I want my copy constructor to take only explicitly converted instances of another object, so I declared it explicit, but now I get the error error "C2558: class 'Mat' : no copy constructor available or copy constructor is declared 'explicit'", even though I made an explicit cast:
static_cast<Mat<int>>(d1)
I've declared the copy constructor explicit because I want this to be illegal:
Mat<float> a;
Mat<int> b(a);
While, I would like the following to remain legal:
Mat<float> a;
Mat<int> b(static_cast<Mat<int>>(a));
EDIT: I've been tinkering with this concepts trying to define exactly what I want to get, and I seem to get some funny results:
#include <iostream>
class MatB
{
private:
float data;
public:
MatB()
:data(0.0f)
{
}
void set(float value)
{
data = value;
}
float getData() const
{
return data;
}
void print()
{
std::cout << data << std::endl;
}
};
class MatA
{
private:
double data;
public:
MatA()
:data(0.0)
{
}
void set(double value)
{
data = value;
}
double getData() const
{
return data;
}
explicit operator MatB()
{
MatB temp;
temp.set(static_cast<float>(getData()));
return temp;
}
void print()
{
std::cout << data << std::endl;
}
};
class MatC
{
private:
int data;
public:
MatC()
:data(0)
{
}
explicit MatC(const MatB& in)
:data(static_cast<int>(in.getData()))
{
}
void print()
{
std::cout << data << std::endl;
}
};
int main()
{
MatA someA;
someA.set(3.14159);
MatC constructCFromA(someA);
someA.print();
constructCFromA.print();
std::cin.sync();
std::cin.ignore();
return 0;
}
In this example, constructCFromA(someA) shouldn't compile (imo) - even the linker marks it as an error(VS2013), still it compiles just fine... I am not sure whether my understanding of 'explicit' is incorrect, whether the IDE marks it as an error incorrectly, or the compiler compiles it even though it shouldn't. I thought I would need to do something like this:
constructCFromA(static_cast<MatB>(someA));
The IDE seems to agree with me, but the compiler doesn't. I must say I am pretty confused.
EDIT2:
Never mind, in Ideone it doesn't compile, so I guess MS are to blame.
I think the 2nd code illustrates well the behaviour I want to get. Basically make non-explicit conversions at initialization and assignment illegal. It seems however, that making the copy constructor explicit has various "side-effects".

The line where you did the explicit cast is not a problem. The problem that causes the compiling issue is on the line where you return Mat<U> by value:
template<class U>
explicit operator Mat<U>()
{
Mat<U> result;
result.set(static_cast<U>(data));
return result; // <<== This line requires a copy constructor to be defined
}
That is why when you remove explicit before the copy ctor, your code works just fine.

here's another version that will pass your unit test without the need for a conversion operator to T:
template<class T>
class Mat
{
private:
T data;
public:
void set(T value)
{
data = value;
}
// default constructor
Mat()
: data(T(0))
{
}
// construct from data type
explicit Mat(T dat)
: data(dat)
{}
// construct from any compatible Mat
template<class U>
explicit Mat(const Mat<U>& another)
: data(static_cast<T>(another.get_data()))
{}
// assign from any compatible Mat
template<class U>
Mat& operator=(const Mat<U>& another)
{
data = static_cast<T>(another.get_data());
return *this;
}
// provide a means to access data from unrelated Mat
const T& get_data() const { return data; }
void print()
{
std::cout << data << std::endl;
}
};

Related

How to redefine the template class constructor via a macro in C++11?

I want to recorded the line which created the shared_ptr in C++ 11.
Here is my way to rewrite shared_ptr as Shared_ptr :
template<class T>
class Shared_Ptr{
public:
Shared_Ptr(T* ptr = nullptr,int line=__LINE__)
:_pPtr(ptr)
, _pRefCount(new int(1))
, _pMutex(new mutex)
{
cout<<this<<"is located in "<<line<<endl;
}
~Shared_Ptr()
{
Release();
cout<<this<<endl;
}
Shared_Ptr(const Shared_Ptr<T>& sp)
:_pPtr(sp._pPtr)
, _pRefCount(sp._pRefCount)
, _pMutex(sp._pMutex)
{
AddRefCount();
}
Shared_Ptr<T>& operator=(const Shared_Ptr<T>& sp)
{
//if (this != &sp)
if (_pPtr != sp._pPtr)
{
Release();
_pPtr = sp._pPtr;
_pRefCount = sp._pRefCount;
_pMutex = sp._pMutex;
AddRefCount();
}
return *this;
}
T& operator*(){
return *_pPtr;
}
T* operator->(){
return _pPtr;
}
int UseCount() { return *_pRefCount; }
T* Get() { return _pPtr; }
void AddRefCount()
{
_pMutex->lock();
++(*_pRefCount);
_pMutex->unlock();
}
private:
void Release()
{
bool deleteflag = false;
_pMutex->lock();
if (--(*_pRefCount) == 0)
{
delete _pRefCount;
delete _pPtr;
deleteflag = true;
}
_pMutex->unlock();
if (deleteflag == true)
delete _pMutex;
}
private:
int *_pRefCount;
T* _pPtr;
mutex* _pMutex;
};
class student
{
int age;
public:
student(int a):age(a)
{
}
}
;
int main()
{
Shared_ptr<student> Tom(new student(24),__LINE__);
}
Is there a way to make Shared_ptr<student>Tom(new student(24)) as same as Shared_ptr <student> Tom(new student(24),__ LINE__) in C++11? In other words , invoke class Constructor with the arguments bound to args.
I tried to use marco to achieve,but I don't know the correct way how to define the macro of template class constructor.
Below is the macro definition I tried to write but wrong
template<typename T>
#define Shared_ptr<T>::Shared_ptr(T*) Shared_ptr<T>::Shared_ptr(T * ,__LINE__)
Replace int line=__LINE__ in constructor parameters with int line = __builtin_LINE(). It's a non-standard compiler extension, but it works at least in GCC, Clang, and MSVC (i.e. most common compilers).
Then Shared_ptr<student> Tom(nullptr); will work.
Shared_ptr<student> Tom(42); will not work, because Shared_ptr doesn't have the right constructor, but it has nothing to do with getting the line number.

How to move an object instead of copying it in c++?

Is there a way where I could move the object GuitarSpec that is created in main instead of it being copied?
So here is the following example:-
There is an Inventory class that has a list of guitars, and to add a guitar, there is a function called addGuitar that takes string, double and GuitarSpec object as an argument.
Inventory
class Inventory {
private:
list<Guitar> inventory;
public:
void addGuitar(const string &, double, const GuitarSpec &spec);
addGuitar function
void Inventory::addGuitar(const string &serialNumber, double price,
const GuitarSpec &spec) {
inventory.emplace_back(serialNumber, price, spec);
}
Guitar Constructor
Guitar::Guitar(const string& serialNumber, double price, const GuitarSpec &spec)
: serialNumber{serialNumber}, price{price}, spec(spec) {
cout << "Guitar Constructor" << endl;
}
Main function:-
Inventory inventory;
inventory.addGuitar(
"1001", 200,
GuitarSpec(toString(FEDER), "starocaster", toString(ELECTRIC),
toString(Wood::SIKTA), toString(Wood::SIKTA)));
Is there a way to move that GuitarSpec object instead of taking a copy of it, or any other better solution?
When you consider moving only one parameter, you might get away with declaring function overloads, one of which would be moving from a temporary. Or you have design where oly temporaries are used, then why don't you follow an "emplace" strategy instead and create new object on-site?
But with two or more parameters moved the number of required overloads would be four, eight and so on. That's not good, in that case perfect forward might be more useful. An example of forwarding single parameter (of type Spec) in C++11 style:
#include <iostream>
#include <utility>
struct Data {
Data(const Data&) { std::cout << "Data copied\n"; }
Data() { std::cout << "Data created\n"; }
};
struct Spec {
Data *ptr;
Spec() : ptr(new Data()) {};
Spec(const Spec& other) : ptr(new Data{*other.ptr}) {};
Spec(Spec && other) : ptr(other.ptr) {
other.ptr = nullptr;
std::cout << "Data moved\n";
}
Spec& operator=(const Spec& other) { ptr = new Data{*other.ptr};
std::cout << "Data copied\n";
return *this; }
Spec& operator=(Spec&& other) { ptr = other.ptr; other.ptr = nullptr;
std::cout << "Data moved\n"; return *this;
}
~Spec() { delete ptr; }
};
struct foo {
Spec d;
template < typename T, std::enable_if_t<std::is_convertible<T, Spec>::value> * = nullptr>
foo(T&& v) : d(std::forward<T>(v)) { }
template <typename T>
auto set_spec(T&& v) -> decltype(v = std::forward<Spec>(v), void())
{ d = std::forward<T>(v); }
};
int main()
{
std::cout << "Move\n";
foo a {Spec()};
a.set_spec(Spec());
std::cout << "Copy\n";
Spec s;
foo b {s};
a.set_spec(s);
}
You have to modify whole chain of responsibility to use that, starting with overloading Inventory's method:
void addGuitar(const string &serialNumber, double price, GuitarSpec&& spec) {
// move, do we want move string?
inventory.emplace_back(serialNumber, price, std::move(spec));
}
Or using perfect forwarding, this template can copy OR move, when appropriate (example without SFINAE):
template <class SN, class SP>
void addGuitar(SN&& serialNumber, double price, SP&& spec)
{
inventory.emplace_back(std::forward<std::string>(serialNumber),
price, std::forward<GuitarSpec>(spec));
}
Technically addGuitar might just be that if we don't want to bother about restricting interface by SFINAE, assuming we would always use it right and nothing wrong may happen (Murphy, put your hand down) if it's not a public interface. A bad assumption in large project with long life and multiple developers.

Template functions by index in C++

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);
}

What are good ways to avoid copying if method's caller doesn't need ownership of the data?

Here is the problem I was thinking about lately. Let's say our interface is a member function that returns object which is expensive to copy and cheap to move (std::string, std::vector, et cetera). Some implementations may compute the result and return a temporary object while others may simply return a member object.
Sample code to illustrate:
// assume the interface is: Vec foo() const
// Vec is cheap to move but expensive to copy
struct RetMember {
Vec foo() const { return m_data; }
Vec m_data;
// some other code
}
struct RetLocal {
Vec foo() const {
Vec local = /*some computation*/;
return local;
}
};
There are also various "clients". Some only read the data, some require an ownership.
void only_reads(const Vec&) { /* some code */ }
void requires_ownership(Vec) { /* some code */ }
Code above composes well, but is not as efficient as it could be. Here are all combinations:
RetMember retmem;
RetLocal retloc;
only_reads(retmem.foo()); // unnecessary copy, bad
only_reads(retloc.foo()); // no copy, good
requires_ownership(retmem.foo()); // copy, good
requires_ownership(retloc.foo()); // no copy, good
What is a good way to fix this situation?
I came up with two ways, but I'm sure there is a better solution.
In my first attempt I wrote a DelayedCopy wrapper that holds either a value of T or a pointer to const T. It is very ugly, requires extra effort, introduces redundant moves, gets in the way of copy elision and probably has many other problems.
My second thought was a continuation-passing style, which works quite well but turns member functions into member function templates. I know, there is std::function, but it has its overhead so performance-wise it may be unacceptable.
Sample code:
#include <boost/variant/variant.hpp>
#include <cstdio>
#include <iostream>
#include <type_traits>
struct Noisy {
Noisy() = default;
Noisy(const Noisy &) { std::puts("Noisy: copy ctor"); }
Noisy(Noisy &&) { std::puts("Noisy: move ctor"); }
Noisy &operator=(const Noisy &) {
std::puts("Noisy: copy assign");
return *this;
}
Noisy &operator=(Noisy &&) {
std::puts("Noisy: move assign");
return *this;
}
};
template <typename T> struct Borrowed {
explicit Borrowed(const T *ptr) : data_(ptr) {}
const T *get() const { return data_; }
private:
const T *data_;
};
template <typename T> struct DelayedCopy {
private:
using Ptr = Borrowed<T>;
boost::variant<Ptr, T> data_;
static_assert(std::is_move_constructible<T>::value, "");
static_assert(std::is_copy_constructible<T>::value, "");
public:
DelayedCopy() = delete;
DelayedCopy(const DelayedCopy &) = delete;
DelayedCopy &operator=(const DelayedCopy &) = delete;
DelayedCopy(DelayedCopy &&) = default;
DelayedCopy &operator=(DelayedCopy &&) = default;
DelayedCopy(T &&value) : data_(std::move(value)) {}
DelayedCopy(const T &cref) : data_(Borrowed<T>(&cref)) {}
const T &ref() const { return boost::apply_visitor(RefVisitor(), data_); }
friend T take_ownership(DelayedCopy &&cow) {
return boost::apply_visitor(TakeOwnershipVisitor(), cow.data_);
}
private:
struct RefVisitor : public boost::static_visitor<const T &> {
const T &operator()(Borrowed<T> ptr) const { return *ptr.get(); }
const T &operator()(const T &ref) const { return ref; }
};
struct TakeOwnershipVisitor : public boost::static_visitor<T> {
T operator()(Borrowed<T> ptr) const { return T(*ptr.get()); }
T operator()(T &ref) const { return T(std::move(ref)); }
};
};
struct Bar {
Noisy data_;
auto fl() -> DelayedCopy<Noisy> { return Noisy(); }
auto fm() -> DelayedCopy<Noisy> { return data_; }
template <typename Fn> void cpsl(Fn fn) { fn(Noisy()); }
template <typename Fn> void cpsm(Fn fn) { fn(data_); }
};
static void client_observes(const Noisy &) { std::puts(__func__); }
static void client_requires_ownership(Noisy) { std::puts(__func__); }
int main() {
Bar a;
std::puts("DelayedCopy:");
auto afl = a.fl();
auto afm = a.fm();
client_observes(afl.ref());
client_observes(afm.ref());
client_requires_ownership(take_ownership(a.fl()));
client_requires_ownership(take_ownership(a.fm()));
std::puts("\nCPS:");
a.cpsl(client_observes);
a.cpsm(client_observes);
a.cpsl(client_requires_ownership);
a.cpsm(client_requires_ownership);
}
Output:
DelayedCopy:
Noisy: move ctor
client_observes
client_observes
Noisy: move ctor
Noisy: move ctor
client_requires_ownership
Noisy: copy ctor
client_requires_ownership
CPS:
client_observes
client_observes
client_requires_ownership
Noisy: copy ctor
client_requires_ownership
Are there better techniques to pass values that avoid extra copies yet are still general (allow returning both temporaries and data members)?
On a side note: the code was compiled with g++ 5.2 and clang 3.7 in C++11. In C++14 and C++1z DelayedCopy doesn't compile and I'm not sure whether it's my fault or not.
There are probably thousands of 'correct' ways. I would favour one in which:
the the method that delivers the reference or moved object is explicitly stated so no-one is in any doubt.
as little code to maintain as possible.
all code combination compile and do sensible things.
something like this (contrived) example:
#include <iostream>
#include <string>
#include <boost/optional.hpp>
// an object that produces (for example) strings
struct universal_producer
{
void produce(std::string s)
{
_current = std::move(s);
// perhaps signal clients that there is something to take here?
}
// allows a consumer to see the string but does not relinquish ownership
const std::string& peek() const {
// will throw an exception if there is nothing to take
return _current.value();
}
// removes the string from the producer and hands it to the consumer
std::string take() // not const
{
std::string result = std::move(_current.value());
_current = boost::none;
return result;
}
boost::optional<std::string> _current;
};
using namespace std;
// prints a string by reference
void say_reference(const std::string& s)
{
cout << s << endl;
}
// prints a string after taking ownership or a copy depending on the call context
void say_copy(std::string s)
{
cout << s << endl;
}
auto main() -> int
{
universal_producer producer;
producer.produce("Hello, World!");
// print by reference
say_reference(producer.peek());
// print a copy but don't take ownership
say_copy(producer.peek());
// take ownership and print
say_copy(producer.take());
// producer now has no string. next peek or take will cause an exception
try {
say_reference(producer.peek());
}
catch(const std::exception& e)
{
cout << "exception: " << e.what() << endl;
}
return 0;
}
expected output:
Hello, World!
Hello, World!
Hello, World!
exception: Attempted to access the value of an uninitialized optional object.

Generic object carrier class - C++

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.