// Author:
// hustos@qq.com
//
#include <stdio.h>
#include <new>
template <bool c>
struct BoolType
{
static const bool value = c;
};
typedef BoolType<false> FalseType;
typedef BoolType<true> TrueType;
template<bool, typename T> struct __has_assign__;
template <typename T>
struct __has_assign__<true, T>
{
typedef int (T::*Sign)(const T &);
typedef char yes[1];
typedef char no[2];
template <typename U, U>
struct type_check;
template <typename _1> static yes &chk(type_check<Sign, &_1::assign> *);
template <typename> static no &chk(...);
static bool const value = sizeof(chk<T>(0)) == sizeof(yes);
};
template <typename T>
struct __has_assign__<false, T>
{
static bool const value = false;
};
template <typename T>
inline int construct_assign_wrap(T &dest, const T &src, TrueType)
{
printf("%s\n", "has ::assign method");
new(&dest) T();
return dest.assign(src);
}
template <typename T>
inline int construct_assign_wrap(T &dest, const T &src, FalseType)
{
printf("%s\n", "does not have ::assign method");
new((&dest)) T(src);
return 1;
}
template <typename T>
inline int construct_assign(T &dest, const T &src)
{
return construct_assign_wrap(dest, src,
BoolType<__has_assign__<__is_class(T), T>::value>());
}
// ======= ======= 使用上面的方法来做个实验 ======= =======
class A
{
public:
A() = default;
A(const A &other)
{
printf("call A::A, this is unsafe method, can not return error code to user\n");
a_ = other.a_;
}
~A() = default;
// note: 这里必须加上 const,否则签名不匹配,会走到 A::A
int assign(const A &other) {
a_ = other.a_;
printf("call A::assigned, this is safe method, can return error code to user\n");
return 0;
}
private:
int a_;
};
int main(int argc, const char *argv[])
{
A a;
A b;
// 自动判断 A 是否有 assign 方法并决定如何将 a 拷贝到 b:
// - 1. 调assign
// - 2. 使用A的拷贝构造函数
construct_assign(b, a);
return 0;
}
编译测试下:
[xiaochu.yh ~/tools] $g++ assign.cpp -std=c++0x -o assign
[xiaochu.yh ~/tools] $./assign
has ::assign method
call A::assigned, this is safe method, can return error code to user