remove_pointer 对于 unique_ptr 的

remove_pointer for unique_ptr's

假设我正在编写一个带有可玩 AI 的棋盘游戏。 class Board 有两个模板参数:P 和 N。N 是玩家的数量。 P 是 unique_ptr<Player>Player。我在实际玩游戏时使用unique_ptr<Player>,因为Player有两个child class(HumanAI),但是当AI搜索游戏状态,它使用相同的 Board class 但 T = Player(我选择这个是为了潜在的性能提升,例如数据将是本地的,间接性更少,堆应该更少碎片化)。

问题: 我如何定义运算符[],其中 returns 是对其中一名玩家的引用(例如,如果 T = unique_ptr 它 returns *arr_[i],否则 returns arr_[i])。下面是一个尝试,但没有编译。另外,请随意评论设计(例如,理论上,我真的可以通过引入 P 看到性能提升吗?)。

template<typename P, size_t N>
class Board
{
public:
  P& operator[] (size_t idx) { return helper(arr[idx]); }
private:
  template<typename I, typename O>
  inline O& helper(I& input)
  {
    return input;
  }
  template<>
  inline P& helper<unique_ptr<P>,P>(unique_ptr<P> input)
  {
    return *input;
  }
  std::array<P,N> arr_;
};

编译器错误:

  1. non-namespace 范围 'class Foo'
  2. 的显式专业化
  3. template-id helper,T> 在声明中 主模板

Also, feel free to comment on design (e.g. in theory, can I really see a performance gain by introducing P?).

好的:

  1. 您甚至在代码编译之前就试图以可维护性换取性能。这是最邪恶的早期优化。

  2. unique_ptr 管理所有权。将它用作您正在寻求做的逻辑开关是交易可维护性和可读性(大时间)以获得尚未确认的性能提升(参见 1)。将 unique_ptr 传递给函数的唯一原因是函数 绝对必须知道 数据由 unique_ptr 管理。这是很少见的(阅读:永远不要这样做)除非你正在转让所有权或者你正在编写一个旨在访问 unique_ptrs

  3. 集合的访问者
  4. 关于代码最重要的事情是这些(按重要性排序):

    1. 它编译
    2. 有效
    3. 逻辑正确,无bug,不泄露资源
    4. 易于维护
    5. 真的很容易维护
    6. 您的用户喜欢使用它
    7. 在这一点上,您可以尝试实现关于编写您能编写的最高效代码的自恋幻想(通常没有充分的理由)。你会失败,但你确实有更好的事情要做——比如让游戏变得更好,玩起来更有趣。

担心性能的时候是当您的用户被完美运行的软件所宠坏时,使用起来非常愉快,他们唯一能想到的担心就是游戏只给他们 299.99每秒帧数,他们认为它确实应该提供 300。

我不会评论这背后的逻辑,但实现它只需要引入一个辅助函数:并使用辅助函数的 return 类型。您在尝试中看到的问题是您的 operator[] 只是 returned P& - 如果 Pstd::unique_ptr<T,D>.

要使用 helper 的 return 类型,我们只需将其设为 private static 并依赖 decltype:

template <typename P, size_t N>
class Board {
private:
    template <typename T, typename D>
    static T& get_helper(std::unique_ptr<T,D>& val) { return *val; }

    template <typename T>
    static T& get_helper(T& val) { return val; }

public:
    decltype(get_helper(std::declval<P&>())) // use the same return type
                                             // as the helper function
    operator[] (size_t idx) {
        return get_helper(arr_[idx]);
   }

private:
    std::array<P,N> arr_;
};

在C++14中,注释掉的行可以是decltype(auto).