使用名称空间作为参数的模板函数?

Template functions using namespace as parameter?

出于性能原因,我必须使用显式操作来制作自己的 类 向量、矩阵、张量等。因为我只使用 2D 或 3D 维度,所以我为每个维度定义了 类 使用命名空间。这是代码的简单草稿:

namespace Dim2 {
    class Vec {
        public:
        double components[2];
    };
    
    class Mat {
        public:
        double components[2][2];
    };
}

namespace Dim3 {
    class Vec {
        public:
        double components[3];
    };
    
    class Mat {
        public:
        double components[3][3];
    };
}

所以如果我需要,例如,一个 3D 矢量,我调用 Dim3::Vec newVec;,我可以执行针对 3 维优化的操作。

现在,假设我想使用如下模板编写通用函数:

template<typename Vec, typename Mat>
void doSomething()
{
    Vec v;
    Mat m;
    // Perform operations
}

这样,如果我想使用 2D 向量,我调用 doSomething<Dim2::Vec, Dim2::Mat>();,对于 3D 向量:doSomething<Dim3::Vec, Dim3::Mat>();.

此解决方案也在 中得到解决,并且工作正常。问题是…… 'real' 代码不仅有向量和矩阵,还有无数其他结构:三阶张量、四阶张量、对称矩阵等。如果我在函数中使用所有这些,调用将是这样的:

doSomething<Dim2::Vec, Dim2::Mat, Dim3::Tensor3, Dim3::Tensor4, Dim4:: SymMat, ...>();

太广泛(而且丑陋)。

为了简短起见,我真正想做的是将命名空间作为模板参数。像这样:

template<typename Dim>
void doSomething()
{
    Dim::Vec v;
    Dim::Mat m;
    Dim::Tensor3 t3;
    Dim::Tensor4 t4;
    Dim::SymMat symMat;
    // Perform operations
}

这样,函数调用将很简单 doSomething<Dim2>();doSomething<Dim3>();

但是,这样做会给我一个编译器错误,因为 C++ 不允许名称空间作为模板参数。我尝试使用嵌套 类(即 Dim2Dim3 作为 类,而不是名称空间)来做同样的事情,但我仍然遇到编译器错误。

我该怎么做才能完成我想做的事情?你们有其他选择吗?

在此先感谢,对于任何英语错误,我们深表歉意。

您可以使用类型 traits-like 帮助程序 structs 来减少用于调用 doSomething().

的参数数量
namespace Dim2 {

    class Vec {
        public:
        double components[2];
    };
    
    class Mat {
        public:
        double components[2][2];
    };

   struct Chooser
   {
      using Vec = Vec;
      using Mat = Mat;
   };
}

namespace Dim3 {
    class Vec {
        public:
        double components[3];
    };
    
    class Mat {
        public:
        double components[3][3];
    };

   struct Chooser
   {
      using Vec = Vec;
      using Mat = Mat;
   };
}

template <typename Chooser>
void doSomething()
{
   using Vec = typename Chooser::Vec;
   using Mat = typename Chooser::Mat;

   Vec v1;
   Mat m1;
}

int main()
{
   doSomething<Dim2::Chooser>();
   doSomething<Dim3::Chooser>();
}