BReferencable: implement const references with specialization

This is simpler and cleaner than my previous attempt. Thanks to Ingo for
suggesting this.
This commit is contained in:
Adrien Destugues
2015-01-27 10:31:08 +01:00
parent 558a3eede1
commit 49e8a3c652
+91 -25
View File
@@ -37,7 +37,7 @@ protected:
// #pragma mark - BReference // #pragma mark - BReference
template<typename Type = BReferenceable, typename ConstType = Type> template<typename Type = BReferenceable>
class BReference { class BReference {
public: public:
BReference() BReference()
@@ -92,34 +92,34 @@ public:
} }
} }
ConstType* Get() const Type* Get() const
{ {
return fObject; return fObject;
} }
ConstType* Detach() Type* Detach()
{ {
Type* object = fObject; Type* object = fObject;
fObject = NULL; fObject = NULL;
return object; return object;
} }
ConstType& operator*() const Type& operator*() const
{ {
return *fObject; return *fObject;
} }
ConstType* operator->() const Type* operator->() const
{ {
return fObject; return fObject;
} }
operator ConstType*() const operator Type*() const
{ {
return fObject; return fObject;
} }
BReference& operator=(const BReference<Type, ConstType>& other) BReference& operator=(const BReference<Type>& other)
{ {
SetTo(other.fObject); SetTo(other.fObject);
return *this; return *this;
@@ -131,14 +131,14 @@ public:
return *this; return *this;
} }
template<typename OtherType, typename OtherConstType> template<typename OtherType>
BReference& operator=(const BReference<OtherType, OtherConstType>& other) BReference& operator=(const BReference<OtherType>& other)
{ {
SetTo(other.Get()); SetTo(other.Get());
return *this; return *this;
} }
bool operator==(const BReference<Type, ConstType>& other) const bool operator==(const BReference<Type>& other) const
{ {
return fObject == other.fObject; return fObject == other.fObject;
} }
@@ -148,7 +148,7 @@ public:
return fObject == other; return fObject == other;
} }
bool operator!=(const BReference<Type, ConstType>& other) const bool operator!=(const BReference<Type>& other) const
{ {
return fObject != other.fObject; return fObject != other.fObject;
} }
@@ -163,38 +163,104 @@ private:
}; };
// #pragma mark - BReference // #pragma mark - BReference<const>
template<typename Type = BReferenceable> template<typename Type>
class BConstReference: public BReference<Type, const Type> { class BReference<const Type> {
public: public:
BConstReference() BReference(Type* object, bool alreadyHasReference = false)
: :
BReference<Type, const Type>() fReference(object, alreadyHasReference)
{ {
} }
BConstReference(Type* object, bool alreadyHasReference = false) BReference(const BReference<const Type>& other)
: :
BReference<Type, const Type>(object, alreadyHasReference) fReference(other)
{ {
} }
BConstReference(const BReference<Type>& other) template<typename OtherType>
BReference(const BReference<OtherType>& other)
: :
BReference<Type, const Type>(other) fReference(other.Get())
{ {
} }
// Allow assignment of a const reference from a mutable one (but not the void SetTo(Type* object, bool alreadyHasReference = false)
// reverse).
BConstReference& operator=(const BReference<Type, Type>& other)
{ {
SetTo(other.Get()); fReference.SetTo(object, alreadyHasReference);
return *this;
} }
void Unset()
{
fReference.Unset();
}
const Type* Get() const
{
return fReference.Get();
}
const Type* Detach()
{
return fReference.Detach();
}
const Type& operator*() const
{
return *fReference;
}
const Type* operator->() const
{
return fReference.Get();
}
operator const Type*() const
{
return fReference.Get();
}
BReference& operator=(const BReference<const Type>& other)
{
fReference = other.fReference;
}
BReference& operator=(Type* other)
{
fReference = other;
}
template<typename OtherType>
BReference& operator=(const BReference<OtherType>& other)
{
fReference = other.Get();
}
bool operator==(const BReference<const Type>& other) const
{
return fReference == other.Get();
}
bool operator==(const Type* other) const
{
return fReference == other;
}
bool operator!=(const BReference<const Type>& other) const
{
return fReference != other.Get();
}
bool operator!=(const Type* other) const
{
return fReference != other;
}
private:
BReference<Type> fReference;
}; };