c++ - 固定数量的参数包元素来初始化模板类
问题描述
一般的想法是有一个通用类来表示n维空间中的一个点(“类Point”)。只要它们的类型相同,它就应该采用任意数量的参数。我使用可变参数模板参数包做到了这一点,它似乎工作正常。
现在我想要一个简单的别名,比如“Point2i”,它一次只接受整数参数(简单,只需指定类型 T)和两个参数(提示二维空间)(这是我到目前为止失败的地方) .
/**
* @brief Point in n-dimensional space.
*/
template <typename T = int> class Point {
public:
/**
* @brief Default constructor for an empty polygon.
* Points have to be added manually via @ref add_point.
*/
template <typename... Ts>
Point(Ts... coords) {
m_coordinates = { std::forward<Ts>(coords)... };
}
/**
* @brief Dimensions of the point coordinate space.
* @return Number of dimensions.
*/
size_t dims() const {
return m_coordinates.size();
}
/**
* @brief Array subscript operator.
* @param dim The dimension you want.
* @return The coordinate in the specified dimension.
*/
T& operator[] (const size_t &dim) {
return m_coordinates[dim];
}
private:
/// Coordinates of the point in n-dimensional space, where n = vector size.
std::vector<T> m_coordinates;
};
template <typename... Ts, typename = typename std::enable_if<sizeof...(Ts) == 2>::type>
using Point2i = Point<int>(Ts...);
问题出在最后两行:“Point2i”的东西不起作用。我从 GCC 9 得到的错误是:“point.h:52:23: error: template parameter pack must be the last template parameter”。
第 52 行是带有“模板”的行
知道如何按照我想要的方式进行这项工作吗?我想对于有 C++ 模板元编程经验的人来说这很容易。
解决方案
我认为using
对于类的构造函数来说这是不可能的。
我能想象的最好的是一个经典的make_something()
功能。
我的意思是……有点像
template <typename... Ts,
typename = typename std::enable_if<sizeof...(Ts) == 2>::type>
Point<int> Point2i (Ts... ts)
{ return { ts... }; }
Off Topic Unrequested Suggestion 1:尽可能使用构造函数初始化列表;避免(如果可能)在构造函数体内进行初始化
我的意思是...而不是
template <typename... Ts>
Point(Ts... coords) {
m_coordinates = { std::forward<Ts>(coords)... };
}
更好
template <typename... Ts>
Point (Ts ... coords) : m_coordinates { std::forward<Ts>(coords)... }
{ }
Off Topic Unrequested 建议2:如果要使用完美转发,请使用转发引用。
所以构造函数变成
template <typename... Ts>
Point (Ts && ... coords) : m_coordinates { std::forward<Ts>(coords)... }
{ } // ^^ <-- add forwarding references
也在point2i
函数中
template <typename... Ts,
typename = typename std::enable_if<sizeof...(Ts) == 2>::type>
Point<int> Point2i (Ts && ... ts)
{ return { std::forward<Ts>(ts)... }; }
Off Topic Unrequested Suggestion 3:我想你的Point
对象是固定大小的。在这种情况下,我建议考虑将点的大小添加为模板参数的假设。这样您就可以使用std::array
而不是std::vector
.
推荐阅读
- android - 如何使用导航架构组件创建 BottomSheetDialogFragment?
- python - Django:如何在我的登录页面上实现一个记住我的键
- r - geom_raster 给出“条纹”结果
- reactjs - React 是使用类名管理多个主题的好方法吗?
- python - 如何获取 GitHub 存储库的贡献者总数?
- java - 在 macOS 上通过 brew 安装 JRE(但不是 JDK)
- angular7 - 如何将数据传递给自定义组件的标记?
- javascript - 如何禁用具有以逗号分隔的多个值的选项?
- android - Android WebView - 滚动条不填充 layout_height
- uinavigationcontroller - 如何从导航控制器中找到可见的 pushViewController?