假设我正在编写一个带有可玩AI的棋盘游戏。 class Board
有两个模板参数:P和N.N是玩家数量。 P是unique_ptr<Player>
或Player
。我在实际玩游戏时使用unique_ptr<Player>
,因为Player
有两个子类(Human
和AI
),但是当AI搜索游戏状态时,它会使用相同的Board
{1}}类,但T = Player(我选择这个来获得潜在的性能提升,例如数据将是本地的,更少的间接性,堆应该更少碎片化)。
问题:我如何定义operator [],它返回对其中一个玩家的引用(例如,如果T = unique_ptr,它返回* arr_ [i],否则返回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_;
};
编译器错误:
答案 0 :(得分:1)
我不会对这背后的逻辑发表评论,但实现它只需要引入辅助函数:并使用帮助程序的返回类型。您在尝试中看到的问题是,您的运营商[]刚刚返回P&
- 如果P
是std::unique_ptr<T,D>
,则该类型将是错误的类型。
要使用帮助者的返回类型,我们只需将其设为私有静态并依赖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)
。
答案 1 :(得分:0)
另外,请随意评论设计(例如,理论上,通过引入P,我能真正看到性能提升吗?)。
好的就是:
您尝试在代码编译之前交换可维护性以获得性能。这是最邪恶的早期优化。
unique_ptr管理所有权。将其用作逻辑开关,正如您正在寻求做的那样是交易可维护性和可读性(大时间)以获得尚未确认的性能提升(参见1)。将unique_ptr传递给函数的唯一原因是函数 absoluteley必须知道数据是由unique_ptr管理的。这是罕见的(阅读:永远不要这样做),除非您转移所有权或者您正在编写一个访问者,该访问者旨在访问unique_ptrs的集合
关于代码最重要的事情是这些(按重要性排序):
担心性能的时候就是当你的用户被如此完美无缺的工作软件所破坏时,使用起来非常愉快,他们唯一可以想到的担心是游戏只给他们299.99帧第二,他们认为真的应该提供300。