19 桥接静态多态与动态多态

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

函数对象指针std::function

#include <iostream>
#include <vector>

template<typename F>
void forUpTo(int n, F f)
{
  for (int i = 0; i < n; ++i) f(i);
}

void print(int i)
{
  std::cout << i << ' ';
}

int main()
{
  std::vector<int> v;
  forUpTo(5, [&v] (int i) { v.push_back(i); });
  forUpTo(5, print); // prints 0 1 2 3 4
}
void forUpTo(int n, void (*f)(int))
{
  for (int i = 0; i < n; ++i) f(i);
}
forUpTo(5, [&v] (int i) { v.push_back(i); }); // 错误:lambda不能转为void(*)(int)
#include <functional>

void forUpTo(int n, std::function<void(int)> f)
{
  for (int i = 0; i < n; ++i) f(i);
}

实现std::function

#include <iostream>
#include <vector>
#include <type_traits>

template<typename R, typename... Args>
class B { // 桥接口:负责函数对象的所有权和操作
 public: // 实现为抽象基类,作为类模板A动态多态的基础
  virtual ~B() {}  
  virtual B* clone() const = 0;
  virtual R invoke(Args... args) const = 0;
};

template<typename F, typename R, typename... Args>
class X : public B<R, Args...> { // 抽象基类的实现
 private:
  F f; // 参数化存储的函数对象类型,以实现类型擦除
 public:
  template<typename T>
  X(T&& f) : f(std::forward<T>(f)) {}

  virtual X* clone() const override
  {
    return new X(f);
  }

  virtual R invoke(Args... args) const override
  {
    return f(std::forward<Args>(args)...);
  }
};

// 原始模板
template<typename Signature>
class A;

// 偏特化
template<typename R, typename... Args>
class A<R(Args...)> {
 private:
  B<R, Args...>* bridge; // 该指针负责管理函数对象
 public:
  A() : bridge(nullptr) {}

  A(const A& other) : bridge(nullptr)
  {
    if (other.bridge)
    {
      bridge = other.bridge->clone();
    }
  }

  A(A& other) : A(static_cast<const A&>(other)) {}

  A(A&& other) noexcept : bridge(other.bridge)
  {
    other.bridge = nullptr;
  }

  template<typename F>
  A(F&& f) : bridge(nullptr) // 从任意函数对象构造
  {
    using Functor = std::decay_t<F>;
    using Bridge = X<Functor, R, Args...>; // X的实例化存储一个函数对象副本
    bridge = new Bridge(std::forward<F>(f)); // 派生类到基类的转换,F丢失,类型擦除
  }

  A& operator=(const A& other)
  {
    A tmp(other);
    swap(*this, tmp);
    return *this;
  }

  A& operator=(A&& other) noexcept
  {
    delete bridge;
    bridge = other.bridge;
    other.bridge = nullptr;
    return *this;
  }

  template<typename F>
  A& operator=(F&& f)
  {
    A tmp(std::forward<F>(f));
    swap(*this, tmp);
    return *this;
  }

  ~A() { delete bridge; }

  friend void swap(A& fp1, A& fp2) noexcept
  {
    std::swap(fp1.bridge, fp2.bridge);
  }

  explicit operator bool() const
  {
    return bridge == nullptr;
  }

  R operator()(Args... args) const
  {
    return bridge->invoke(std::forward<Args>(args)...);
  }
};

void forUpTo(int n, A<void(int)> f)
{
  for (int i = 0; i < n; ++i) f(i);
}

void print(int i)
{
  std::cout << i << ' ';
}

int main()
{
  std::vector<int> v;
  forUpTo(5, [&v] (int i) { v.push_back(i); });
  forUpTo(5, print);
}
virtual bool equals(const B* fb) const = 0;
virtual bool equals(const B<R, Args...>* fb) const override
{
  if (auto specFb = dynamic_cast<const X*> (fb))
  {
    return f == specFb->f; // 要求f有operator==
  }
  return false;
}
friend bool operator==(const A& f1, const A& f2) {
  if (!f1 || !f2)
  {
    return !f1 && !f2;
  }
  return f1.bridge->equals(f2.bridge); // equals要求operator==
}

friend bool operator!=(const A& f1, const A& f2)
{
  return !(f1 == f2);
}
template<typename T>
class IsEqualityComparable {
 private:
  static void* conv(bool);
  template<typename U>
  static std::true_type test(
    decltype(conv(std::declval<const U&>() == std::declval<const U&>())),
    decltype(conv(!(std::declval<const U&>() == std::declval<const U&>())))
  );

  template<typename U>
  static std::false_type test(...);
 public:
  static constexpr bool value = decltype(test<T>(nullptr, nullptr))::value;
};

// 构造一个TryEquals在调用类型没有合适的==时抛出异常
template<typename T, bool EqComparable = IsEqualityComparable<T>::value>
struct TryEquals {
  static bool equals(const T& x1, const T& x2)
  {
    return x1 == x2;
  }
};

class NotEqualityComparable : public std::exception {};

template<typename T>
struct TryEquals<T, false> {
  static bool equals(const T& x1, const T& x2)
  {
    throw NotEqualityComparable();
  }
};
virtual bool equals(const B<R, Args...>* fb) const override
{
  if (auto specFb = dynamic_cast<const X*> (fb))
  {
    return TryEquals<F>::equals(f, specFb->f);
  }
  return false;
}

性能考虑

上一篇 下一篇

猜你喜欢

热点阅读