为模板化的特定情况添加构造函数 class

Adding a constructor for specific case of templated class

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

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

我还想为 Vect<2> 设置一个别名 Vect2D,使用 typedef 或其他任何可以完成此工作的别名(例如,我下面的解决方案)。

这是我的一些代码 class 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<2>Vect<2> 不是 a Vect2D,所以当我在两个 Vect2D 之间使用运算符时,returned 对象的类型为 Vect<2>,因此如果需要我将其转换回 Vect2D 最后一行,例如,如果函数的 return 类型是 Vect2D,而我 return 是两个 Vect2D 之间的运算符的结果。它完成了工作,但这也是我觉得这个解决方案有点脏的部分原因。)

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

如何避免完全 class 专业化和 SFINAE 仅在 N 为 2 时才启用双精度构造函数?

有点像

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

I'd also like to have an alias Vect2D for Vect<2>, either with a typedef or anything else that does the job

使用 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)
 }