operator overloading c++ (x==y==z) - c++

I have encountered a strange problem, that I don't know how to solve in overloading.
Im trying too overload operator == .
The easy example would be:
class bla{
public:
int a;
void bla(int a):a(a){}//costructor
bool operator==(const bla& ob)
return (a==ob.a);//chk if equal
};
void main(){
bla A,B;
if (A==B)
flag=1;//just an example...
this is easy and works great, i'm trying to handle the case of:
if (A==B==C==D)
so i need to return type object and now type bool.
i have tried to add another function :
bla &bla:: operator==(const bool answer){//as a member function
if (answer)
return *this;
but it doesn't seem to help. have any suggestions?
thx Stas

This is a horrible idea and you should never do it.
Here is how you do it.
#include <type_traits>
template<typename T, typename U>
struct decay_equiv
: std::is_same<
typename std::decay<T>::type,
typename std::decay<U>::type
>::type {};
template<typename T>
struct comparator {
bool res;
T passalong;
explicit operator bool() { return res; }
typename std::enable_if<
!decay_equiv<T, comparator<T> >::value,
comparator<T>
>::type operator==(T const& rhs);
comparator<T> operator==(comparator<T> const& rhs);
};
template<typename T>
typename std::enable_if<
!decay_equiv<T, comparator<T>>::value,
comparator<T>
>::type comparator<T>::operator==(T const& rhs) {
if (!res) {
return {res, rhs};
}
return {(passalong == rhs).res, rhs};
}
template<typename T>
comparator<T> comparator<T>::operator==(comparator<T> const& rhs) {
if (!res || !rhs.res) {
return {res, rhs};
}
return {(passalong == rhs.passalong).res, rhs.passalong};
}
struct bla {
int a;
comparator<bla> operator==(bla const& rhs);
comparator<bla> operator==(comparator<bla> const& rhs);
};
comparator<bla> bla::operator==(bla const& rhs) {
return {a == rhs.a, rhs};
}
comparator<bla> bla::operator==(comparator<bla> const& rhs) {
if (!rhs.res) {
return rhs;
}
return {a == rhs.passalong.a, rhs.passalong};
}
int main() {
bla a = {0},b = {0},d = {0};
if (a==b==d)
return 0;
return -1;
}
This code assumes C++11, but can be written in C++98 with only very minor changes.

i have managed to find a different approach and it seems to work great.
thx to u all for your help and suggestions.
class bla{
public:
int a;
bool f;
void bla(int a):a(a){f = true;}//costructor
operator bool(){return f};
bla& operator==(const bla &ob){//chk if equal
if (f)
f=(a==ob.a);
return *this;
}
};
void main(){
bla A(4),B(4),C(4),D(4);
if (A==B==C==D)
flag=1;//just an example...

Related

Design issue with template map with takes different structures

Problem Description and Question
I have a template class Class1. It contains in map in which I want to insert structures A or B.
The problem is that the structures A and B have different types of member variables. Structure A has an std::string member variable whereas structure B has an int member variable.
The comparator is based on structure A. So obviously when I want to insert a structure B it will not compile.
Class1<B,B> c2;
c2.AddElement({1},{1});
How can I fix that design Issue? For instance is it possible to keep Class1 as template class and do something to TestCompare?
I also have a constraint. I cannot modify the structures A and B. they are written in C code. I have no right to change them because they are external codes used by other users. I just simplified the code as much as possible.
Source Code
The code was compiled on cpp.sh
#include <iostream>
#include <string>
#include <map>
typedef struct {
std::string a;
} A;
typedef struct {
int b;
} B;
template<typename T1, typename T2> class Class1 {
public :
struct TestCompare {
bool operator()(const T1 & lhs, const T1 & rhs) const {
return lhs.a < rhs.a;
}
};
Class1() {}
~Class1() {}
void AddElement(const T1 & key, const T2 & value) {
m.emplace(key, value);
}
private :
std::map<T1,T2,TestCompare> m;
};
int main()
{
Class1<A,A> c1;
c1.AddElement({"1"},{"1"});
// Problem here. Obviously it will not compile because the Operator is using
// the member variable of struct A.
//Class1<B,B> c2;
//c2.AddElement({1},{1});
//return 0;
}
New Source code
// Example program
#include <iostream>
#include <string>
#include <map>
typedef struct {
std::string a;
} A;
typedef struct {
int b;
} B;
bool operator<(const A & lhs, const A & rhs) {
return lhs.a < rhs.a;
}
bool operator<(const B & lhs, const B & rhs) {
return lhs.b < rhs.b;
}
template<typename T1, typename T2> class Class1 {
public :
Class1() {}
~Class1() {}
void AddElement(const T1 & key, const T2 value) {
m.emplace(key, value);
}
std::map<T1,T2> getMap() {
return m;
}
private :
std::map<T1,T2> m;
};
int main()
{
Class1<A,A> c1;
c1.AddElement({"1"},{"1"});
// Problem here. Obviously it will not compile because the Operator is using
// the member variable of struct A.
Class1<B,B> c2;
c2.AddElement({1},{1});
c2.AddElement({2},{2});
for(const auto &e: c2.getMap()) {
std::cout << e.first.b << " " << e.first.b << std::endl;
}
return 0;
}
I guess you could remove TestCompare from Class1 and template that.
template<typename T> struct TestCompare {
bool operator()(const T & lhs, const T & rhs) const {
// default implementation
return lhs < rhs;
}
};
template<typename T1, typename T2> class Class1 {
...
private :
std::map<T1,T2,TestCompare<T1>> m;
}
You could then specialise TestCompare for A and B
template<> struct TestCompare<A> {
bool operator()(const A & lhs, const A & rhs) const {
return lhs.a < rhs.a;
}
};
template<> struct TestCompare<B> {
bool operator()(const B & lhs, const B & rhs) const {
return lhs.b < rhs.b;
}
};
EDIT:
Actually you could just use std::less instead of TestCompare. It amounts to pretty much the same thing, and std::map uses std::less by default.
TestCompare requires that every type you use must have a member a that can be compared using <. That's a lot of requirements, which implies a terrible design. Add a 3rd template parameter that will be used to pass a function or a functor that compares the objects
struct CompareA {
bool operator()(A const & lhs, A const & rhs) const {
return lhs.a < rhs.a;
}
};
struct CompareB {
bool operator()(B const& lhs, B const& rhs) const {
/*...*/
}
};
template<typename KeyT, typename ValueT, typename Compare> class Dict {
public :
Class1() {}
~Class1() {}
void AddElement(KeyT const & key, ValueT const & value) {
m.emplace(key, value);
}
private :
std::map<KeyT, ValueT, Compare> m;
};
Dict<A, B, CompareA> dictA;
Dict<B, B CompareB> dictB;
You could specialize the struct TestCompare, like john has suggested in his answer, and provide it as the default template argument
template<typename KeyT, typename ValueT, typename Compare = TestCompare<KeyT>> class Dict { /*...*/ };
Such solution will allow you to provide only 2 arguments, like so
Dict<B, B> dict;
while still maintaining the ability to provide another comparer if necessary.

Transparent comparator code minimization

Let's say we store a struct with a string key and we want to find it by that string in a container like std::set, so common implementation would look like this:
struct Foo {
std::string id;
};
struct FooComp {
using is_transparent = std::true_type;
bool operator()( const Foo &foo, const std::string &str ) const
{
return foo.id < str;
}
bool operator()( const std::string &str, const Foo &foo ) const
{
return str < foo.id;
}
bool operator()( const Foo &foo1, const Foo &foo2 ) const
{
return foo1.id < foo2.id;
}
};
std::set<Foo,FooComp> foo_set;
...
This works fine, but writing three methods for FooComp that do prety match the same (logically) is monotonic and error prone. Is there a way to minimize that code?
You may do as following:
struct Foo {
std::string id;
};
struct FooComp {
using is_transparent = std::true_type;
template <typename LHS, typename RHS>
bool operator()(const LHS& lhs, const RHS& rhs) const
{
return ProjectAsId(lhs) < ProjectAsId(rhs);
}
private:
const std::string& ProjectAsId(const std::string& s) const { return s; }
const std::string& ProjectAsId(const Foo& foo) const { return foo.id; }
};
You write comparison once, but you have to write the projection for each type.
In C++17, it can even be
template <auto f> struct ProjLess
{
using is_transparent = std::true_type;
template <typename LHS, typename RHS>
bool operator()(const LHS& lhs, const RHS& rhs) const
{
return project(lhs) < project(rhs);
}
private:
template <typename T>
using f_t = decltype(std::invoke(f, std::declval<const T&>()));
template <typename T>
using is_f_callable = is_detected<f_t, T>;
template <typename T, std::enable_if_t<is_f_callable<T>::value>* = nullptr>
decltype(auto) project(const T& t) const { return std::invoke(f, t); }
template <typename T, std::enable_if_t<!is_f_callable<T>::value>* = nullptr>
const T& project(const T& t) const { return t; }
};
And usage:
std::set<Foo, ProjLess<&Foo::id>> s;
Demo with C++17
My solution is all in the class:
struct FooComp {
using is_transparent = std::true_type;
struct FooProj {
std::string const& str;
FooProj( std::string const& sin ):str(sin) {}
FooProj( const Foo& foo ):str(foo.id) {}
FooProj( FooProj const& ) = default;
friend bool operator<(FooProj lhs, FooProj rhs) {
return lhs.str < rhs.str;
}
};
bool operator()( FooProj lhs, FooProj rhs ) const
{
return lhs<rhs;
}
};
This doesn't support types that can convert to std::string.
However, when doing a projection-based comparison, I do this:
template<class F, class After=std::less<>>
auto order_by( F&& f, After&& after={} ) {
return
[f=std::forward<F>(f), after=std::forward<After>(after)]
(auto&& rhs, auto&&lhs)->bool {
return after( f(decltype(lhs)(lhs)), f(decltype(rhs)(rhs)) );
};
}
which takes a projection and generates a comparison function for it. We make it transparent with:
template<class F>
struct as_transparent_t {
F f;
using is_transparent=std::true_type;
template<class Lhs, class Rhs>
bool operator(Lhs const& lhs, Rhs const& rhs)const{ return f(lhs, rhs); }
};
template<class F>
as_transparent_f<std::decay_t<F>>
as_transparent( F&& f ) { return {std::forward<F>(f)}; }
so we can project and be transparent via:
as_transparent( order_by( some_projection ) );
which only leaves the projection.
In C++14 we just do a
std::string const& foo_proj_f( std::string const& str ) { return str; }
std::string const& foo_proj_f( Foo const& foo ) { return foo.id; }
auto foo_proj = [](auto const& x)->decltype(auto){ return foo_proj_f(x); };
auto foo_order = as_transparent( order_by( foo_proj ) );
which breaks things down into modular chunks.
In C++17 we can use if constexpr:
auto foo_proj = [](auto const& x)->std::string const& {
if constexpr( std::is_same<decltype(x), std::string const&>{} ) {
return x;
}
if constexpr( std::is_same<decltype(x), Foo const&>{} ) {
return x.id;
}
};
auto foo_order = as_transparent( order_by( foo_proj ) );
or
template<class...Ts>
struct overloaded:Ts...{
using Ts::operator()...;
overloaded(Ts...ts):Ts(std::move(ts)...){}
};
template<class...Ts> overloaded -> overloaded<Ts...>;
which permits
auto foo_proj = overloaded{
[](std::string const& s)->decltype(auto){return s;},
[](Foo const& f)->decltype(auto){return f.id;}
};
which may be easier to read than the if constexpr version. (This version can also be adapted to c++14 or c++11).

how to avoid many similar overloads for C strings

Here is the code:
template <typename L, typename R> bool eq (const L& lhs, const R& rhs) { return lhs == rhs; }
template<int N> bool eq(char* lhs, const char(&rhs)[N]) { return String(lhs).compare(rhs) == 0; }
template<int N> bool eq(const char(&lhs)[N], char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(char* lhs, char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(const char* lhs, const char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(char* lhs, const char* rhs) { return String(lhs).compare(rhs) == 0; }
inline bool eq(const char* lhs, char* rhs) { return String(lhs).compare(rhs) == 0; }
I have to do this for neq/lt/gt/lte/gte and not just for equality. Maybe I've already missed something.
Is there a way to not list all the possible combinations of C string types?
Also C++98.
EDIT: >> here << is an online demo with the problem
Decay an array type to pointer:
template<class T>
struct decay_array { typedef T type; };
template<class T, size_t N>
struct decay_array<T[N]> { typedef T* type; };
template<class T>
struct decay_array<T[]> { typedef T* type; };
Check that a type is not a pointer to (possibly const) char:
template<class T>
struct not_char_pointer { enum { value = true }; };
template<>
struct not_char_pointer<char*> { enum { value = false }; };
template<>
struct not_char_pointer<const char*> { enum { value = false }; };
Now check that a type is not a pointer to or array of (possibly const) char:
template<class T>
struct can_use_op : not_char_pointer<typename decay_array<T>::type> {};
Reimplement std::enable_if:
template<bool, class = void>
struct enable_if {};
template<class T>
struct enable_if<true, T> { typedef T type; };
and use it to constrain your template:
template <typename L, typename R>
typename enable_if<can_use_op<L>::value || can_use_op<R>::value, bool>::type
eq (const L& lhs, const R& rhs) { return lhs == rhs; }
Then just one overload is enough:
inline bool eq(const char* lhs, const char* rhs) { return String(lhs).compare(rhs) == 0; }
namespace details{
template<template<class...>class Z,class,class...Ts>
struct can_apply:std::false_type{};
template<template<class...>class Z,class...Ts>
struct can_apply<Z,std::void_t<Z<Ts...>>,Ts...>:std::true_type{};
}
template<template<class...>class Z,class...Ts>
using can_apply=details::can_apply<Z,void,Ts...>;
This tests if a template can be applied some types.
namespace strcmp{
bool eq(const char*lhs, const char*rhs){/* body */}
}
template<class L, class R>
using str_eq_r=decltype(strcmp::eq(std::declval<L>(),std::declval<R>()));
template<class L, class R>
using can_str_eq=can_apply<str_eq_r,L,R>;
can_str_eq is truthy iff we can call stdcmp::eq on it.
namespace details {
bool eq(const char* lhs, const char* rhs, std::true_type){
return strcmp::eq(lhs,rhs);
}
template<class L,class R>
bool eq(L const& l, R const&r,std::false_type){
return l==r;
}
}
template<class L,class R>
bool eq(L const& l, R const&r){
return details::eq(l,r,can_str_eq<L const&,R const&>{});;
}
We could also use a static_if trick to do it inline, if you like:
template<class L,class R>
bool eq(L const& l, R const&r){
return static_if<can_str_eq>( l, r )(
strcmp::eq,
[](auto&& l, auto&& r){return l==r;}
);
}
After writing a static_if:
template<class...Ts>
auto functor(Ts...ts){
return [=](auto&& f){
return f(ts...);
};
}
namespace details{
template<class Functor>
auto switcher(std::true_type, Functor functor){
return [=](auto&& t, auto&&){
return functor(t);
};
}
template<class Functor>
auto switcher(std::false_type, Functor functor){
return [=](auto&&, auto&& f){
return functor(f);
};
}
}
template<template<class...>class test, class...Ts>
auto static_if(Ts...ts){
return details::switcher(
test<Ts...>{},
functor(ts...)
);
}
now, what are the odds that works? (Written on phone, not compiled yet) Also not optimal: lots of perfect forwarding, some of which requires de-lamdaing, required.

Iterator "pointing" to a member of an object

I admit I had difficulties coming up with a reasonable description for this. I cannot think of a good term that would describe precisely what I'm looking for. Perhaps this could be called a slicing iterator.
Let's say I have something like this:
struct S
{
int i;
char *s;
float f;
};
std::vector<S> v(10);
What I'm looking for is a way to construct an iterator, that would point to a member of S. I'd like to be able to pass it to something like std::min_element without creating a predicate in each case. Something that might look like this:
std::min_element(slicing_iterator(v.begin(), S::f), slicing_iterator(v.end(), S::f));
Is there any template trick that I could use to achieve this? Or perhaps it's already done somewhere in Boost or some other library?
If you're looking for an iterator that converts S into its S::f, this could certainly be done using boost (what can't be?):
std::cout << *std::min_element(
boost::make_transform_iterator(v.begin(), boost::bind(&S::f, _1)),
boost::make_transform_iterator(v.end(), boost::bind(&S::f, _1))
) << '\n';
test: https://ideone.com/jgcHr
But if you're looking for the S whose S::f is the smallest in the vector, the predicate is the most reasonable approach.
If you don't want to create a predicate function for each case, I would suggest not to look for a slicing operator, but to implement your predicate as a lambda function (either using Boost or C++0x). Here you will find a detailed explanation
http://www.codeproject.com/KB/cpp/Sort.aspx
(this is about std::sort, but the comparison in std::min_element works equally.)
Will something like this do the job?
#include <algorithm>
#include <iostream>
#include <vector>
struct S
{
int i;
float f;
S() : i(0), f(0.0f) {}
S(int i_, float f_) : i(i_), f(f_) {}
};
template <typename Iterator, typename T, typename M>
class SlicingIterator : public std::iterator<typename Iterator::iterator_category,M>
{
private:
Iterator m_it;
M T::*m_m;
public:
SlicingIterator(const Iterator& it, M T::*m)
: m_it(it), m_m(m)
{}
const M operator*() const
{
return (*m_it).*m_m;
}
bool operator!=(const SlicingIterator& rhs) const
{
return m_it != rhs.m_it;
}
SlicingIterator& operator++()
{
++m_it;
return *this;
}
bool operator<(const SlicingIterator& rhs) const
{
return m_it < rhs.m_it;
}
};
template <typename Iterator, typename T, typename M>
SlicingIterator<Iterator,T,M> slicing_iterator(const Iterator& it, M T::*m)
{
return SlicingIterator<Iterator,T,M>(it, m);
}
int main()
{
std::vector<S> vec;
vec.push_back(S(23,9));
vec.push_back(S(17,10));
std::copy(slicing_iterator(vec.begin(), &S::f), slicing_iterator(vec.end(), &S::f), std::ostream_iterator<float>(std::cout, " "));
return 0;
}
In addition to what is already suggested you may do it almost exactly like your code sample does.
Example:
template< class IterT, class ObjT, class MemberT >
class slicing_iterator;
template< class IterT, class ObjT, class MemberT >
inline bool operator==(
const slicing_iterator<IterT,ObjT,MemberT>& a,
const slicing_iterator<IterT,ObjT,MemberT>& b
);
template< class IterT, class ObjT, class MemberT >
inline bool operator!=(
const slicing_iterator<IterT,ObjT,MemberT>& a,
const slicing_iterator<IterT,ObjT,MemberT>& b
);
template< class IterT, class ObjT, class MemberT >
class slicing_iterator
{
IterT m_iter;
MemberT ObjT::* m_member;
public:
slicing_iterator( IterT iter, MemberT ObjT::*member ) :
m_iter(iter), m_member(member)
{
}
slicing_iterator& operator++() { ++m_iter; return *this; }
slicing_iterator& operator--() { --m_iter; return *this; }
MemberT& operator*() { return static_cast<ObjT&>(*m_iter).*m_member; }
const MemberT& operator*() const { return static_cast<const ObjT&>(*m_iter).*m_member; }
MemberT* operator->() { return &m_iter->*m_member; }
const MemberT* operator->() const { return &m_iter->*m_member; }
private:
friend bool operator== <IterT,ObjT,MemberT>(
const slicing_iterator<IterT,ObjT,MemberT>& a,
const slicing_iterator<IterT,ObjT,MemberT>& b
);
friend bool operator!= <IterT,ObjT,MemberT>(
const slicing_iterator<IterT,ObjT,MemberT>& a,
const slicing_iterator<IterT,ObjT,MemberT>& b
);
};
template< class IterT, class ObjT, class MemberT >
inline bool operator==(
const slicing_iterator<IterT,ObjT,MemberT>& a,
const slicing_iterator<IterT,ObjT,MemberT>& b
)
{
return a.m_iter == b.m_iter && a.m_member == a.m_member;
}
template< class IterT, class ObjT, class MemberT >
inline bool operator!=(
const slicing_iterator<IterT,ObjT,MemberT>& a,
const slicing_iterator<IterT,ObjT,MemberT>& b
)
{
return a.m_iter != b.m_iter || a.m_member != a.m_member;
}
template< class IterT, class ObjT, class MemberT >
inline slicing_iterator<IterT,ObjT,MemberT>
make_slicing_iterator( IterT iter, MemberT ObjT::*member )
{
return slicing_iterator<IterT,ObjT,MemberT>( iter, member );
}
struct S
{
int i;
char *s;
float f;
};
int main(void)
{
std::vector<S> v(10);
std::min_element(
make_slicing_iterator(v.begin(), &S::f),
make_slicing_iterator(v.end(), &S::f)
);
return 0;
}
At first I didn't notice - it looks similar to what #Stuart Golodetz suggested but the advantage is that operator< doesn't have to be defined for iterator type (e.g. std::list::iterator). It makes this implementation universal.

clone_ptr problem, I need to create a copy object using a function of the library instead of new

I am a bit new to templates in C++ so forgive me if this question is confusing or stupid, I just have a problem where I want to implement a clone smart pointer so I don't have to create copy constructors for each and every class that uses my underlying XML library that only seems to use object pointers and not smart pointers. The problem is that my traits need to create the new objects using functions from the underlying library and I do not know how I would go about doing that in a template/traits class. I have posted all the code with some comments below, if anybody could advice, I'd appreciate it.
If something is unclear, please ask and I will try to clarify.
#ifndef CLONE_PTR_H
#define CLONE_PTR_H
#include <algorithm>
#include <functional>
#include <xercesc/dom/DOM.hpp>
#include <xercesc/dom/DOMDocument.hpp>
struct DOMObject_cloner
{
static DOMDocument* clone(DOMDocument* pPtr)
{
DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(X("Core")); // this looks wrong, depends on DOMIMplementation_cloner being done really... how do I do this properly
return pPtr ? : impl->createDocument(...) //I need this function for a DOMDocument* to be created!!!
}
};
struct DOMImplementation_cloner
{
static DOMImplementation* clone(DOMImplementation* pPtr)
{
return pPtr ? DOMImplementationRegistry::getDOMImplementation(X("Core")) : 0;
}
};
template<typename T>
struct default_clone
{
static T* clone(T* pPtr)
{
return pPtr ? pPtr->clone() : 0;
}
};
template <typename T, typename Cloner = default_clone<T> >
class clone_ptr
{
public:
// types
typedef T element_type;
typedef element_type value_type;
typedef const element_type const_value_type;
typedef value_type* pointer;
typedef const_value_type* const_pointer;
typedef value_type& reference;
typedef const_value_type& const_reference;
// creation
clone_ptr() :
mPtr(0)
{}
explicit clone_ptr(pointer pPtr) :
mPtr(pPtr)
{}
clone_ptr(const clone_ptr& pOther) :
mPtr(pOther.get() ? Cloner()(pOther.get()) : 0)
{}
/*clone_ptr(const clone_ptr& pOther) :
mPtr(pOther.get() ? pOther->clone() : 0),
{}*/
clone_ptr& operator=(clone_ptr pOther)
{
swap(*this, pOther);
return *this;
}
~clone_ptr()
{
delete get();
}
// observers
pointer get() const
{
return mPtr;
}
pointer operator->() const
{
return get();
}
reference operator*() const
{
assert(get() != 0);
return *get();
}
// modifiers
pointer release()
{
pointer result = mPtr;
mPtr = 0;
return result;
}
void reset(pointer pPtr = 0)
{
*this = clone_ptr(pPtr);
}
// utility
friend void swap(clone_ptr& pFirst, clone_ptr& pSecond)
{
std::swap(pFirst.mPtr, pSecond.mPtr);
}
private:
pointer mPtr;
//default_clone Cloner;
};
template <typename T1>
bool operator!(const clone_ptr<T1>& pX)
{
return pX.get() == 0;
};
template <typename T1, typename T2>
bool operator>=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst < pSecond);
};
// compare
template <typename T1, typename T2>
bool operator==(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return pFirst.get() == pSecond.get();
};
template <typename T1, typename T2>
bool operator!=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst == pSecond);
};
template <typename T1, typename T2>
bool operator<(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return std::less<void*>()(pFirst.get(), pSecond.get());
};
template <typename T1, typename T2>
bool operator<=(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return !(pFirst > pSecond);
};
template <typename T1, typename T2>
bool operator>(const clone_ptr<T1>& pFirst, const clone_ptr<T2>& pSecond)
{
return pSecond < pFirst;
};
#endif
I am not really sure if I understand your question, but I see one thing wrong with your code. DOMObject_cloner and DOMImplementation_cloner should be specializations of default_clone, like this:
template<>
struct default_clone<DOMDocument> {
static DOMDocument* clone(DOMDocument* pPtr)
{
DOMImplementation* impl = DOMImplementationRegistry::getDOMImplementation(X("Core"));
return pPtr ? : impl->createDocument(...);
}
};
Template specialization is the whole point of traits in C++.