【问题标题】:Template functions using namespace as parameter?使用命名空间作为参数的模板函数?
【发布时间】:2021-01-08 01:41:50
【问题描述】:

出于性能原因,我必须使用显式操作创建自己的向量、矩阵、张量等类。由于我只使用 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&lt;Dim2::Vec, Dim2::Mat&gt;();,对于 3D 向量:doSomething&lt;Dim3::Vec, Dim3::Mat&gt;();

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

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&lt;Dim2&gt;();doSomething&lt;Dim3&gt;();

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

我可以做些什么来完成我想要的?各位有什么办法吗?

提前致谢,对于任何英文错误,我们深表歉意。

【问题讨论】:

  • 有点笨拙,您可以创建一个struct Dim3_ns { using Vec = Dim3::Vec; /*et cetera*/ };,然后使用doSomething&lt;Dim3_ns&gt;() { ...

标签: c++ templates namespaces


【解决方案1】:

您可以使用类似类型特征的帮助器 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>();
}

【讨论】:

  • 看起来不错,非常感谢!但是,例如,如果我希望 Vec 成为函数的参数怎么办?喜欢void doSomething(Vec v1)
  • @PericlesCarvalho,函数重载可以解决这个问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-19
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-08
  • 1970-01-01
相关资源
最近更新 更多