25 模板的调试

2021-06-04  本文已影响0人  奇点创客

浅实例化(Shallow Instantiation)

template<typename T>
void f1(T& p)
{
  *p = 0; // assumes T is a pointer-like type
}

template<typename T>
void f2(T& p)
{
  f1(p);
}

template<typename T>
void f3(typename T::Type p)
{
  f2(p);
}

template<typename T>
void f4(const T& x)
{
  typename T::Type i;
  f3<T>(i);
}

class X {
 public:
  using Type = int;
};

int main()
{
  X x;
  f4(x); // 错误(只能在实例化时被检测到)
}
f4(x)
// 实例化
f4<X>(const X&)
// 实例化
f3<X>(X::Type)
// 实例化
f2<X::Type>(X::Type&)
// 实例化
f1<X::Type>(X::Type&)
// 即
f1(int& p)
{
  *p = 0; // 出错
}
void ignore(const T&) {}

template<typename T>
void f4(const T& x)
{
  class ShallowChecks
  {
    void deref(typename T::Type p)
    {
      ignore(*p);
    }
  };
  typename T::Type i;
  f3(i);
}

静态断言(Static Assertion)

static_assert(sizeof(void*) * CHAR_BIT == 64, "Not a 64-bit platform");
template<typename T>
class HasDereference {
 private:
  template<typename U> struct Identity;
  template<typename U> static std::true_type
    test(Identity<decltype(*std::declval<U>())>*);
  template<typename U> static std::false_type
    test(...);
 public:
  static constexpr bool value = decltype(test<T> (nullptr))::value;
};

void f4 (const T& x)
{
  static_assert(HasDereference<T>::value, "T is not dereferenceable");
  typename T::Type i;
  f3(i);
}
template<typename T>
class C {
  static_assert(HasDereference<T>::value, "T is not dereferenceable");
  static_assert(std::is_default_constructible_v<T>, "T is not default constructible");
  ...
};

原型(Archetype)

// 要求T必须是可比较的类型,即两个T对象能用==比较,且结果为bool
template<typename T>
int find(const T* a, int n, const T& val)
{
  int i = 0;
  while (i != n && a[i] != val) ++i;
  return i;
}
class EqualityComparableArchetype {};

class ConvertibleToBoolArchetype {
 public:
  operator bool() const; // 提供本类型到bool的隐式转换
};

ConvertibleToBoolArchetype // 返回类型要求能转换为bool
operator==(const EqualityComparableArchetype&, const EqualityComparableArchetype&);

// 实例化find<EqualityComparableArchetype>
template int find(const EqualityComparableArchetype*, int,
  const EqualityComparableArchetype&);
template<typename T>
int find(const T* a, int n, const T& val)
{
  int i = 0;
  while (i != n && !(a[i] == val)) ++i;
  return i;
}
class ConvertibleToBoolArchetype {
 public:
  operator bool() const;
  bool operator!() = delete;
};

跟踪程序(Tracer)

class SortTracer {
 private:
  int value; // integer value to be sorted
  int generation; // generation of this tracer
  inline static long n_created = 0; // number of constructor calls
  inline static long n_destroyed = 0; // number of destructor calls
  inline static long n_assigned = 0; // number of assignments
  inline static long n_compared = 0; // number of comparisons
  inline static long n_max_live = 0; // maximum of existing objects

  // recompute maximum of existing objects
  static void update_max_live()
  {
    if (n_created-n_destroyed > n_max_live)
    {
      n_max_live = n_created-n_destroyed;
    }
  }
 public:
  static long creations() { return n_created; }
  static long destructions() { return n_destroyed; }
  static long assignments() { return n_assigned; }
  static long comparisons() { return n_compared; }
  static long max_live() { return n_max_live; }
 public:
  // constructor
  SortTracer(int v = 0) : value(v), generation(1)
  {
    ++n_created;
    update_max_live();
    std::cerr << "SortTracer #" << n_created
      << ", created generation " << generation
      << " (total: " << n_created - n_destroyed
      << ")\n";
  }

  // copy constructor
  SortTracer(const SortTracer& b) : value(b.value), generation(b.generation + 1)
  {
    ++n_created;
    update_max_live();
    std::cerr << "SortTracer #" << n_created
      << ", copied as generation " << generation
      << " (total: " << n_created - n_destroyed
      << ")\n";
  }

  // destructor
  ~SortTracer()
  {
    ++n_destroyed;
    update_max_live();
    std::cerr << "SortTracer generation " << generation
      << " destroyed (total: "
      << n_created - n_destroyed << ")\n";
  }

  // assignment
  SortTracer& operator=(const SortTracer& b)
  {
    ++n_assigned;
    std::cerr << "SortTracer assignment #" << n_assigned
      << " (generation " << generation
      << " = " << b.generation
      << ")\n";
    value = b.value;
    return *this;
  }

  // comparison
  friend bool operator<(const SortTracer& a, const SortTracer& b)
  {
    ++n_compared;
    std::cerr << "SortTracer comparison #" << n_compared
      << " (generation " << a.generation
      << " < " << b.generation
      << ")\n";
    return a.value < b.value;
  }

  int val() const { return value; }
};
int main()
{
  SortTracer input[] = { 7, 3, 5, 6, 4, 2, 0, 1, 9, 8 };

  // 打印初始值
  for (int i = 0; i < 10; ++i)
  {
    std::cerr << input[i].val() << ' ';
  }
  std::cerr << '\n';

  // 记录初始条件
  long created_at_start = SortTracer::creations();
  long max_live_at_start = SortTracer::max_live();
  long assigned_at_start = SortTracer::assignments();
  long compared_at_start = SortTracer::comparisons();

  // 执行std::sort
  std::cerr << "---[ Start std::sort() ]--------------------\n";
  std::sort<>(&input[0], &input[9]+1);
  std::cerr << "---[ End std::sort() ]----------------------\n";

  // 检查结果
  for (int i = 0; i < 10; ++i)
  {
    std::cerr << input[i].val() << ' ';
  }
  std::cerr << "\n\n";

  // final report
  std::cerr << "std::sort() of 10 SortTracer's was performed by:\n"
    << SortTracer::creations() - created_at_start
    << " temporary tracers\n"
    << "up to "
    << SortTracer::max_live()
    << " tracers at the same time ("
    << max_live_at_start << " before)\n"
    << SortTracer::assignments() - assigned_at_start
    << " assignments\n"
    << SortTracer::comparisons() - compared_at_start
    << " comparisons\n\n";
}
std::sort() of 10 SortTracer's was performed by:
9 temporary tracers
up to 11 tracers at the same time (10 before)
33 assignments
42 comparisons

Oracles

上一篇 下一篇

猜你喜欢

热点阅读