使用C ++可变参数模板通过类构造函数传递数组

时间:2018-01-26 20:14:10

标签: c++ arrays c++11 constructor variadic-templates

我想使用新的C ++范例(我有一个C ++ 17编译器)对一个小型数学库进行现代化。具体来说,我需要通过构造函数将数组传递给类。

这是"经典"我使用的旧方式。它的工作原理

class Vector {
public:
    long double* elements;
public:
    Vector(int size, long double *array) {
        elements = new long double[size];
        for(int i = 0; i < size; i++) {
            elements[i] = array[i];
        }
    };

    virtual ~Vector() {
        delete []elements;
    }

};

int main() {
    long double array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    Vector vector = Vector(10, array);
    for (int i = 0; i < 10; i++) {
        std::cout << vector.elements[i] << std::endl;
    }

    return 0;
}

所以,我尝试用我对variadic模板和参数包的理解来改变Vector类。它不起作用

class Vector {

public:
    long double* elements;
public:
    template<typename... Args>
    Vector(Args... args){
        constexpr int size = sizeof...(Args);
        elements = new long double[size]{args...};
    }
};

int main() {
    long double array[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 0};
    Vector vector = Vector(array);
    for (int i = 0; i < 10; i++) {
        std::cout << vector.elements[i] << std::endl;
    }

    return 0;
}

编译器返回的错误是

  

错误:初始化

中无法将'long double *'转换为'long double'
    elements = new long double[size]{args...};

我做错了什么? 此外,我想知道是否可以在main方法和Vector类中使用std :: array而不是raw数组。

3 个答案:

答案 0 :(得分:2)

传递类似变量模板的数组不是解决方案。可变参数模板用于将 N 个参数传递给类/函数。但是你只传递了一个参数!

我建议你

我建议您使用所有C ++版本中提供的数组引用:

class Vector {
public:
    long double* elements;
public:
    template<std::size_t size>
    Vector(long double (&array)[size]) {
        elements = new long double[size];
        for(int i = 0; i < size; i++) {
            elements[i] = array[i];
        }
    };

    virtual ~Vector() {
        delete []elements;
    }
};

顺便说一句,如果可以,请使用矢量。我非常怀疑这个自定义向量类与std::vector一样高效(没有几何增长或优化的复制和移动)

答案 1 :(得分:1)

根据您的定义

 template<typename... Args> Vector(Args... args);

您希望以这种方式使用此构造函数:

 Vector vector = Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 0);

如果您将构造函数的定义明确地修改为:

,则有可能
template<typename... Args>
Vector(Args... args){
    constexpr int size = sizeof...(Args);
    elements = new long double[size]{static_cast<long double>(args)...};
}

请注意,此类用法良好做法,您通常应使用std容器并避免使用new运营商。

答案 2 :(得分:1)

我不确定这是否能回答你的问题,但我会给你一个一般建议: 我想你想把你自己的逻辑封装到矢量中。 标准库矢量非常先进,您应该使用它,而不是浪费时间编写自己的低级代码。你可以更专注于你需要的逻辑。

您可以定义自己的向量,并仍然使用std :: vector的优点来构建Vector对象。 例如继承:

template<typename T>
class Vector : public std::vector<int>
{
   // here comes the implementation of your interface.
}

或作文:

template<typename T>
class Vector {
private:
    std::vector<T> elems;
}

在组合的情况下,您必须定义所需的构造函数。

在这两种情况下,您都可以使用自己的Vector,如下所示:

Vector<double> vec1(10);         // construct vector with 10 double's each = 0
Vector<double> vec2(10, 5);      // construct vector with 10 double's each = 5
Vector<double> vec3{1,2,3,4};    // using initializer list
Vector<double> vec4(somecontainer.begin(), somecontainer.end());   // construct vector by copying elemts from some other container 

正如您在std :: vector中所看到的,您将获得构建自己的Vector对象所需的所有好处。