【问题标题】:Adding a constructor for specific case of templated class为模板类的特定情况添加构造函数
【发布时间】:2021-05-02 16:12:52
【问题描述】:

我正在实现一个模板类 Vect<std::size_t N>,一个 N 个向量 double。一般构造函数采用std::array<double, N> const& 数组,但我希望例如N=2 有一个采用2 double 的构造函数,以允许更轻的实例化。

我想到了一个效果很好的解决方案(见下文),但感觉有点脏。我已经解决了很多这里提出的问题和他们的答案,但我还没有找到适合我的问题的解决方案。

我还想为Vect<2> 指定一个别名Vect2D,可以是typedef 或其他任何可以完成这项工作的东西(例如,我下面的解决方案)。

这是我班级Vect的一些代码:

template<std::size_t N> class Vect{
protected:
    std::array<double,N> v;
public:
    Vect(const std::array<double,N>& _v = {}): v(_v) {}
    
    /*  bunch of methods & operators  */
};

这是我现在的解决方案:

class Vect2D : public Vect<2>{
public:
    Vect2D(double x = 0, double y = 0): Vect({x,y}) {}
    Vect2D(const Vect<2>& other): Vect(other){}
};

(我必须添加最后一行,因为 Vect2D Vect&lt;2&gt;Vect&lt;2&gt; 不是 Vect2D,所以当我使用两个Vect2D之间的运算符,返回的对象的类型为Vect&lt;2&gt;,所以如果需要,我用最后一行将它转换回Vect2D,例如,如果函数的返回类型是Vect2D,我返回的是两个 Vect2D 之间的运算符的结果。它可以完成工作,但这也是我觉得这个解决方案有点脏的部分原因。)

如果有人有好的解决方案,我将不胜感激,否则这没什么大不了的,因为无论如何我的解决方案都能满足我的需求。

【问题讨论】:

  • Vect&lt;2&gt; x{ {1.0,2.0} }; 不行吗?
  • 如果你有工作代码,你希望同行评审以改进,你的帖子应该在Code Review 上——这就是该网站存在的全部原因。本网站用于解决代码问题,使其无法正常工作或根本无法正常工作。
  • 你的问题到底是什么——你想完全避免Vect2D,避免重复继承的构造函数,或者其他什么?为避免重复构造函数,可以使用using Vect::Vect;
  • @largest_prime_is_463035818 完全是;我的意思是要有一个更轻的符号,即使它看起来没有必要。
  • @rustyx 我基本上想知道是否有一种更清洁的方式来做我所做的事情(正如 Ken White 指出的那样,这可能不是问这个问题的地方),因为我觉得处理通过继承有点脏(也许它毕竟不是)。另外,我已经尝试过using Vect::Vect;,但是在我在问题末尾描述的情况下,将Vect&lt;2&gt; 隐式转换为Vect2D 是行不通的。

标签: c++ templates constructor template-specialization


【解决方案1】:

仅当N 为 2 时,避免全类专业化和 SFINAE 启用二重构造器怎么样?

某事

template <std::size_t M = N, std::enable_if_t<(M == 2), int> = 0>
Vect (double x = 0, double y = 0): v{x,y} {}

我还想为Vect&lt;2&gt; 指定一个别名Vect2D,可以是typedef 或其他任何可以完成这项工作的东西

using怎么样?

using Vect2D = Vect<2>;

以下是带有外部构造函数实现的完整编译示例。

#include <array>
#include <type_traits>

template <std::size_t N>
class Vect
 {
   protected:
      std::array<double, N> v;

   public:
      Vect (std::array<double, N> const & v0 = {});

      template <std::size_t M = N, std::enable_if_t<(M == 2), int> = 0>
      Vect (double x = 0, double y = 0);
 };

template <std::size_t N>
Vect<N>::Vect (std::array<double, N> const & v0) : v{v0}
 { }

template <std::size_t N>
template <std::size_t M, std::enable_if_t<(M == 2), int>>
Vect<N>::Vect (double x, double y) : v{x,y}
 { }

// explicit deduction guide
Vect (double, double) -> Vect<2u>;

int main()
 {
   Vect<2u>  v2{1.0, 2.0};    // compile
   Vect      v2bis{1.0, 2.0}; // compile as Vect<2> (thanks to the deduction guide)
   // Vect<3u>  v3{1.0, 2.0}; // compilation error (no matching constructor)
 }

【讨论】:

  • Vect2D -> Vect 在第一个 sn-p 中?否则我不明白
  • @largest_prime_is_463035818 - 哦!不仅是:v 而不是 Vect 用于数组初始化。谢谢。
  • 那将是我的下一条评论;)我认为这是故意委托构造函数
  • @largest_prime_is_463035818 - “我认为这是一个故意委托的构造函数” - 记住Hanlon Razor:“永远不要将愚蠢归咎于恶意” :(
  • 我对模板很陌生,所以我不知道enabled_if_t 这个东西,谢谢你提出这个问题。我正在调查这个。关于别名的事情,我已经想通了,我只是添加了这一行,而不是在阅读器上添加隐式约束,关于我的解决方案,它直接定义了 Vect2D。还是谢谢你:)
猜你喜欢
  • 1970-01-01
  • 2011-05-08
  • 1970-01-01
  • 2011-09-15
  • 2011-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多