【发布时间】:2014-10-28 11:12:42
【问题描述】:
我正在编写模板化的短向量和小矩阵类,它们不限于具有 2-3-4 个元素,而是可以具有任意数量的元素。
template <typename T, size_t N>
class ShortVector
{
public:
...
template <size_t I> T& get() { return m_data[I]; }
template <size_t I> const T& get() const { return m_data[I]; }
private:
T m_data[N];
};
我希望访问接口是静态的,以便我可以专门化该类以使用内置向量寄存器来获取该类的支持大小。 (可能它们是 AVX、C++AMP 或 OpenCL 向量。)问题是为这个类编写所有理想的运算符(一元-、+、-、*、/、点、长度……)需要很多模板递归,我什至还没有实现矩阵向量和矩阵矩阵乘法,我需要嵌套递归。
现在我有非成员友元运算符和一个私有成员类,其中包含各种静态函数,例如
template <size_t I, typename T1, typename T2> struct Helpers
{
static void add(ShortVector& dst, const ShortVector<T1, N>& lhs, const ShortVector<T2, N>& rhs)
{
dst.get<I>() = lhs.get<I>() + rhs.get<I>();
Helpers<I - 1, T1, T2>::add(dst, lhs, rhs);
}
...
};
template <typename T1, typename T2> struct Helpers < 0, T1, T2 >
{
static void add(ShortVector& dst, const ShortVector<T1, N>& lhs, const ShortVector<T2, N>& rhs)
{
dst.get<0>() = lhs.get<0>() + rhs.get<0>();
}
...
};
为所有运算符编写这样的静态函数和特化感觉是错误的。以这种方式编写更复杂的操作非常容易出错。我正在寻找的是类似的东西
static_for< /*Whatever's needed to define something like a run-time for cycle*/, template <size_t I, typename... Args> class Functor>();
或者几乎任何让我省略大部分样板代码的东西。我已经开始编写这样一个类,但我无法通过合理的专业化编译它。我觉得我仍然缺乏编写这样一个类(或函数)的技能。我查看了其他库,例如 Boost MPL,但还没有完全致力于使用它。我还查看了可能也有用的 std::index_sequence。
虽然 std::index_sequence 似乎是最便携的解决方案,但它有一个我不愿意查看的重大缺陷。最终,这些类必须与SYCL 兼容,这意味着我仅限于使用 C++11,包括模板元编程技术。 std::integer_sequence 是 C++14 STL 库的补充,虽然语言标准的这种限制仅在语言特性方面很重要,但没有什么能阻止 STL 实现者在实现 C++14 STL 时使用 C++14 语言特性功能,因此使用 C++14 STL 功能可能无法移植。
我愿意接受建议,甚至是解决方案。
编辑
Here 是我迄今为止提出的。这是我开始收集的模板元编程技巧的标题,for 循环将是下一个。助手需要一个以运行索引为第一个参数的函子,并接受各种谓词。只要下一次迭代的谓词成立,它就会继续实例化函子。可以将运行索引增加任意数字、乘以数字等。
【问题讨论】:
-
提示:没有人说“循环”。这是一个循环结构
-
你可以让你的
helper类接受一个函数对象,该函数对象实际上决定了计算的内容,然后在实际operators 的定义中使用 lambda 调用它 -
查看 Eigen,它可能会为您节省大量工作:eigen.tuxfamily.org/index.php?title=Main_Page
-
这是什么意思:“我想让访问接口是静态的,这样我就可以专门化这个类来使用内置向量寄存器来支持班上”。究竟什么是“内置向量寄存器”?其余的是什么意思?投票结束,因为不清楚。
-
我 认为 OP 使用
static(错误地)表示使用模板参数而不是函数参数,并希望专门化操作以使用 SIMD或兼容数组类型和长度的 GPU 操作。
标签: c++ c++11 boost stl c++-amp