/**
@brief 生成一个比较器(Comparator),兼键提取(KeyExtractor)类
使用这个宏生成的比较器可以作用在不同的对象上,只要这些对象有相同名称的成员,
并且可以作用在类型为成员类型的对象上。
- 假设:
- 有 n 个类 class[1], class[2], ... class[n],都有类型为 MemberType ,名称为 MemberName 的数据成员
- 那么以下类型的对象可以使用该类相互比较,并且可以从这些对象中提取出 MemberType 类型的键:
class[1] ... class[n], MemberType, 以及所有这些类型的任意级别的指针
@param ComparatorName 比较器类的名字
@param MemberType 要比较的对象的成员类型
@param MemberName 要比较的对象的成员名字,也可以是一个成员函数调用,
前面必须加 '.' 或者 '->', 加 '->' 只是为用于 smart_ptr/iterator/proxy 等重载 '->' 的对象
当用于裸指针时,仍使用 '.',这意味着裸指针和 smart_ptr/iterator/proxy
不能使用同一个生成的 Comparator,虽然裸指针的语法和它们都相同
@param ComparePred 比较准则,这个比较准则将被应用到 XXXX MemberName
@note
- 这个类不是从 ComparePred 继承,为的是可以允许 ComparePred 是个函数,
但这样(不继承)阻止了编译器进行空类优化
- 不在内部使用 const MemberType&, 而是直接使用 MemberType,
是为了允许 MemberName 是一个函数时,返回一个即时计算出来的 Key;
- 当为了效率需要使用引用时,将 const MemberType& 作为 MemberType 传进来
- 当 MemberType 是个指针时,将 Type* 作为 MemberType ,而非 const Type*,即使 MemberType 真的是 const Type*
- 注意 C++ 参数推导机制:
@code
template<T> void f(const T& x) { } // f1
template<T> void f(const T* x) { } // f2
template<T> void g(const T& x) { } // g1
template<T> void g(const T* x) { } // g2
template<T> void g( T& x) { } // g3
template<T> void g( T* x) { } // g4
void foo()
{
int a;
const int b;
f(&a); // call f1, T was deduced as int*, and then convert to 'const int*&', so match f1, not f2
f(&b); // call f2, T was deduced as int
g(&a); // call g4, T was deduced as int
g(&b); // call g2, T was deduced as int
}
@endcode
在上述代码已经表现得比较明白了,这就是要生成四个不同 deref 版本的原因
- 为了配合上述机制,传入的 MemberType 不要有任何 const 修饰符
*/
#define SAME_NAME_MEMBER_COMPARATOR_EX(ComparatorName, MemberType, MemberName, ComparePred) /
class ComparatorName /
{ /
ComparePred m_comp; /
public: /
typedef bool result_type; /
typedef MemberType key_type; /
typedef boost::integral_constant<bool, /
febird::HasTriCompare<ComparePred>::value /
> has_tri_compare; /
/
ComparatorName() {} /
ComparatorName(const ComparePred& rhs) /
: m_comp(rhs) {} /
/
template<class T>const T&deref(T*x)const{return*x;} /
template<class T>const T&deref(T&x)const{return x;} /
template<class T>const T&deref(const T*x)const{return*x;}/
template<class T>const T&deref(const T&x)const{return x;}/
/
const MemberType operator()(const MemberType x)const{return x;} /
template<class T>const MemberType operator()(const T&x)const{return deref(x)MemberName;}/
/
template<class Tx, class Ty> /
bool operator()(const Tx&x, const Ty&y) const /
{ /
return m_comp((*this)(x),(*this)(y)); /
} /
template<class Tx, class Ty> /
int compare(const Tx&x, const Ty&y) const /
{ /
return m_comp.compare((*this)(x),(*this)(y)); /
} /
};
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#endif
// #define SAME_NAME_MEMBER_COMPARATOR_EX(ComparatorName, MemberType, MemberName, ComparePred) /
// SAME_NAME_MEMBER_COMPARATOR_EX_NO_TRAITS(ComparatorName, MemberType, MemberName, ComparePred)/
// BOOST_TT_AUX_BOOL_TRAIT_SPEC1(HasTriCompare, ComparatorName, HasTriCompare<ComparePred>::value)
//! note@ if MemberType must not be a reference, neither const nor non-const
#define SAME_NAME_MEMBER_COMPARATOR(ComparatorName, MemberType, MemberName) /
SAME_NAME_MEMBER_COMPARATOR_EX(ComparatorName, MemberType, MemberName, std::less<MemberType>)