C++ 为模板化类的特定情况添加构造函数

C++ 为模板化类的特定情况添加构造函数,c++,templates,constructor,template-specialization,C++,Templates,Constructor,Template Specialization,我正在实现一个模板类Vect,一个Ndouble的向量。一般构造函数采用std::array const&array,但我希望例如N=2的构造函数采用2double,以允许更轻的实例化 我想到了一个很好的解决方案(见下文),但感觉有点脏。我已经研究了这里提出的许多问题及其答案,但我还没有找到一个非常适合我的问题的解决方案 我还希望为Vect提供一个别名Vect2D,可以是typedef,也可以是其他任何执行此任务的工具(例如,我下面的解决方案) 下面是我的课程的一些代码Vect: templat

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

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

我还希望为
Vect
提供一个别名
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  */
};
模板类向量{
受保护的:
std::数组v;
公众:
Vect(const std::array&_v={}):v(_v){}
/*一组方法和运算符*/
};
以下是我目前的解决方案:

class Vect2D : public Vect<2>{
public:
    Vect2D(double x = 0, double y = 0): Vect({x,y}) {}
    Vect2D(const Vect<2>& other): Vect(other){}
};
类Vect2D:公共向量{
公众:
Vect2D(双x=0,双y=0):Vect({x,y}){
Vect2D(const-Vect&other):Vect(other){}
};
(我必须添加最后一行,因为
Vect2D
Vect
Vect
不是
Vect2D
,所以当我在两个
Vect2D
之间使用运算符时,返回的对象的类型为
Vect
,因此如果需要,我用最后一行将其转换回
Vect2D
,例如,如果函数是
Vect2D
,我返回的是两个
Vect2D
之间的运算符的结果。它完成了任务,但这也是我觉得这个解决方案有点脏的部分原因。)


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

如果避免全类专门化,并且只有当
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} {}
下面是使用外部构造函数实现的完整编译示例

#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)
 }
#包括
#包括
模板
类向量
{
受保护的:
std::数组v;
公众:
Vect(std::array const&v0={});
模板
向量(双x=0,双y=0);
};
模板
Vect::Vect(std::array const&v0):v{v0}
{ }
模板
模板
Vect::Vect(双x,双y):v{x,y}
{ }
//明确演绎指南
Vect(双,双)->Vect;
int main()
{
Vect v2{1.0,2.0};//编译
Vect v2bis{1.0,2.0};//编译为Vect(感谢演绎指南)
//Vect v3{1.0,2.0};//编译错误(没有匹配的构造函数)
}

vectx{{1.0,2.0}
不正常?如果你有工作代码,你想让同行评审以改进,你的帖子应该放在上面-这就是网站存在的全部原因。这个网站是为了解决代码问题,这些问题会妨碍它正常工作或根本无法正常工作。你的问题到底是什么-你想完全避免
Vect2D
吗d重复继承的构造函数,或者smth?为了避免重复构造函数,可以使用
using Vect::Vect;
@maximust\u prime\u is\u 463035818完全是这样;我的目的是使用一个更轻的符号,即使它看起来不必要。@rustyx我基本上想知道是否有一种更干净的方法来完成我的工作(正如Ken White所指出的,这可能不是问这个问题的地方),因为我觉得通过继承进行处理有点脏(也许根本不是)另外,我已经试过使用Vect::Vect;来
,但是隐式地将
Vect
转换成
Vect2D
是行不通的,比如我在问题末尾描述的例子。
Vect2D
->
Vect
,否则我不会understand@largest_prime_is_463035818-哦!不仅如此:
v
而不是
Vect
用于数组初始化。谢谢。这将是我的下一个评论;)我认为它是purpose@largest_prime_is_463035818-“我认为这是一个故意授权的构造器”-记住:“永远不要将愚蠢充分解释的东西归因于恶意”:(我对模板很陌生,所以我不知道这个
启用\u if\t
的问题,谢谢你提出。我正在研究这个问题。关于别名的问题,我已经知道了,我只是添加了这一行,以避免对读卡器添加隐式约束,关于我的解决方案,它直接定义了
Vect2D
。谢谢无论如何:)
#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)
 }