#include <iostream>
#include <string>
#include <boost/ref.hpp>
#include <boost/variant.hpp>
template <typename T>
class CopyOrRef
{
private:
typedef const T CopyType;
typedef typename boost::reference_wrapper<const T> RefType;
boost::variant<CopyType, RefType> _copyOrRef;
public:
CopyOrRef(const T & value) : _copyOrRef(value) { std::cout << "ctor 1" << std::endl; } // stores copy
CopyOrRef(const T * ptr) : _copyOrRef(boost::ref(*ptr)) { std::cout << "ctor 2" << std::endl; } // stores reference
CopyOrRef(const boost::reference_wrapper<T> & r) : _copyOrRef(boost::cref(r.get())) { std::cout << "ctor 3" << std::endl; } // stores reference
CopyOrRef(const boost::reference_wrapper<const T> & r) : _copyOrRef(r) { std::cout << "ctor 4" << std::endl; } // stores reference
const T & get()
{
return _copyOrRef.which() == 0 ?
*(boost::get<CopyType>(&_copyOrRef)) :
*(boost::get<RefType>(&_copyOrRef));
}
bool isCopy() const { return _copyOrRef.which() == 0; }
bool isRef() const { return _copyOrRef.which() == 1; }
};
class NonCopyConstructible
{
public:
NonCopyConstructible() {}
private:
NonCopyConstructible(NonCopyConstructible & that);
};
int main()
{
std::string s = "s";
CopyOrRef<std::string> test1(s);
CopyOrRef<std::string> test2("ss");
CopyOrRef<std::string> test3(&s);
CopyOrRef<std::string> test4(boost::ref(s));
CopyOrRef<std::string> test5(boost::cref(s));
std::cout << "test1: isCopy=" << test1.isCopy() << ", isRef=" << test1.isRef() << " : " << test1.get() << std::endl;
std::cout << "test2: isCopy=" << test2.isCopy() << ", isRef=" << test2.isRef() << " : " << test2.get() << std::endl;
std::cout << "test3: isCopy=" << test3.isCopy() << ", isRef=" << test3.isRef() << " : " << test3.get() << std::endl;
std::cout << "test4: isCopy=" << test4.isCopy() << ", isRef=" << test4.isRef() << " : " << test4.get() << std::endl;
std::cout << "test5: isCopy=" << test5.isCopy() << ", isRef=" << test5.isRef() << " : " << test5.get() << std::endl;
NonCopyConstructible t;
CopyOrRef<NonCopyConstructible> tt(boost::cref(t));
}