C++利用模板檢測是否包含某個函數,並決定生成什麼樣的調用代碼

// Author:
//   [email protected]
//
#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
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章