使用variadic模板作为属性

时间:2017-09-18 13:27:00

标签: c++ c++14 variadic

几个星期前,我问question关于"变种的问题"矩阵课,现在我试图在不同的项目中应用答案,我收到错误,我不明白。基本上问题是我不明白如何使用" variadic" matrix class作为另一个类中的属性(在最小工作示例中名为Test)。

最小的工作示例 main.cpp中:

#include <iostream>
#include <memory>
#include "matrix.hpp"
#include "test.hpp"
using namespace std;

int main(int argc, char *argv[])
{
    Test T();
    return 0;
}

matrix.hpp:

#ifndef MATRIX_H
#define MATRIX_H

template<typename T>
class Matrix 
     {
      private:
        std::vector<size_t> dimensions;
        std::unique_ptr<T[]> _data;

      public:
        Matrix() 
        {}

        Matrix(std::vector<size_t> dims) 
        : dimensions(std::move(dims)) 
        {
            size_t size = flat_size();
            _data = std::make_unique<T[]>(size);
         }

         template<typename ... Dimensions>
         Matrix(size_t dim, Dimensions&&... dims) 
         {
           size_t size = apply_dimensions(dim, std::forward<Dimensions>(dims)...);
          _data = std::make_unique<T[]>(size);
         }   

         template<typename ... Indexes>
         T & operator()(size_t idx, Indexes&& ... indexes) 
         {
            if (sizeof...(indexes)+1 != dimensions.size())
                 throw std::runtime_error("Incorrect number of parameters used to retrieve Matrix Data!");
            size_t flat_index = get_flat_index(0, idx, std::forward<Indexes>(indexes)...);
            return at(flat_index);
         }

        template<typename ... Indexes>
        T const& operator()(size_t idx, Indexes&& ... indexes) const 
        {
            if (sizeof...(indexes)+1 != dimensions.size())
                throw std::runtime_error("Incorrect number of parameters used to retrieve Matrix Data!");
            size_t flat_index = get_flat_index(0, idx, std::forward<Indexes>(indexes)...);
            return at(flat_index);
        }

        Matrix(const Matrix&) 
        {}

        Matrix(Matrix&& other)
        : Matrix() 
        {
            swap(*this, other);
        }

        Matrix & operator=(Matrix other)
        {
            swap(*this, other); 
            return *this;
        }

        friend void swap(Matrix& first, Matrix& second) 
        {
            using std::swap;
            swap(first.dimensions, second.dimensions);
            swap(first._data, second._data);
         }


         size_t dimension_size(size_t dim) const {
            return dimensions[dim];
         }

        size_t num_of_dimensions() const {
            return dimensions.size();
        }

     private:
   template<typename ... Dimensions>
    size_t apply_dimensions(size_t dim, Dimensions&& ... dims)
    {
        dimensions.emplace_back(dim);
        return dim * apply_dimensions(std::forward<Dimensions>(dims)...);
    }

    size_t apply_dimensions(size_t dim) 
    {
        dimensions.emplace_back(dim);
        return dim;
    }

    template<typename ... Indexes>
    size_t get_flat_index(size_t dim, size_t index, Indexes&& ... indexes) const 
    {
        return get_offset(index, dim) + get_flat_index(dim + 1, std::forward<Indexes>(indexes)...);
    }

    size_t get_flat_index(size_t dim, size_t index) const 
    {
        return get_offset(index, dim);
    }

    size_t get_offset(size_t index, size_t dim) const 
    {
        if (index >= dimensions[dim])
            throw std::runtime_error("Index out of Bounds");
        for (size_t i = dim + 1; i < dimensions.size(); i++) 
        {
            index *= dimensions[i];
        }
        return index;
    }

    T& at(size_t flat_index) {
        return _data[flat_index];
    }

    T const& at(size_t flat_index) const {
        return _data[flat_index];
    }

    size_t flat_size() const {
        size_t size = 1;
        for (size_t dim : dimensions)
            size *= dim;
        return size;
    }
 };

 #endif // MATRIX_H

test.hpp:

#ifndef TEST_H
#define TEST_H
#include "matrix.hpp"
#include <vector>
#include <memory>
class Test
{
public:
    Test();
    Matrix<double>* temp = NULL;
    Matrix<double> mat;
};
#endif // TEST_H

TEST.CPP:

#include "test.hpp"

Test::Test()
{
    mat = Matrix<double>{9, 2, 8};
}

使用&#34; g ++ -std = c ++ 14 * .cpp -o cfd.out&#34;进行编译后,出现以下类型的错误:

matrix.hpp:8:14: error: ‘vector’ in namespace ‘std’ does not name a template type
     std::vector<size_t> dimensions;
          ^
matrix.hpp:15:27: error: expected ‘)’ before ‘<’ token
     Matrix(std::vector<size_t> dims) 
                       ^
matrix.hpp: In member function ‘T& Matrix<T>::operator()(size_t, Indexes&& ...)’:
matrix.hpp:32:41: error: ‘dimensions’ was not declared in this scope
         if (sizeof...(indexes)+1 != dimensions.size())
                                     ^
matrix.hpp: In member function ‘const T& Matrix<T>::operator()(size_t, Indexes&& ...) const’:
matrix.hpp:41:41: error: ‘dimensions’ was not declared in this scope
         if (sizeof...(indexes)+1 != dimensions.size())
                                     ^
matrix.hpp: In member function ‘size_t Matrix<T>::dimension_size(size_t) const’:
matrix.hpp:71:20: error: ‘dimensions’ was not declared in this scope
         return dimensions[dim];
matrix.hpp: In member function ‘size_t Matrix<T>::num_of_dimensions() const’:
matrix.hpp:75:20: error: ‘dimensions’ was not declared in this scope
         return dimensions.size();
                ^
matrix.hpp: In member function ‘size_t Matrix<T>::apply_dimensions(size_t, Dimensions&& ...)’:
matrix.hpp:82:13: error: ‘dimensions’ was not declared in this scope
         dimensions.emplace_back(dim);
         ^
matrix.hpp: In member function ‘size_t Matrix<T>::apply_dimensions(size_t)’:
matrix.hpp:88:13: error: ‘dimensions’ was not declared in this scope
         dimensions.emplace_back(dim);
         ^
matrix.hpp: In member function ‘size_t Matrix<T>::get_offset(size_t, size_t) const’:
matrix.hpp:105:26: error: ‘dimensions’ was not declared in this scope
         if (index >= dimensions[dim])
                      ^
matrix.hpp:107:42: error: ‘dimensions’ was not declared in this scope
         for (size_t i = dim + 1; i < dimensions.size(); i++) 
                                      ^
matrix.hpp: In member function ‘size_t Matrix<T>::flat_size() const’:
matrix.hpp:124:31: error: ‘dimensions’ was not declared in this scope
         for (size_t dim : dimensions)
                           ^
In file included from test.hpp:3:0,
             from test.cpp:1:
matrix.hpp:8:14: error: ‘vector’ in namespace ‘std’ does not name a template type
     std::vector<size_t> dimensions;
          ^
matrix.hpp:9:14: error: ‘unique_ptr’ in namespace ‘std’ does not name a template type
     std::unique_ptr<T[]> _data;
          ^
matrix.hpp:15:27: error: expected ‘)’ before ‘<’ token
     Matrix(std::vector<size_t> dims) 
                       ^
matrix.hpp:23:23: error: expected ‘)’ before ‘dim’
     Matrix(size_t dim, Dimensions&&... dims) 
                   ^
matrix.hpp:30:24: error: ‘size_t’ was not declared in this scope
     T & operator()(size_t idx, Indexes&& ... indexes) 
                    ^
matrix.hpp:30:43: error: expected primary-expression before ‘&&’ token
     T & operator()(size_t idx, Indexes&& ... indexes) 
                                       ^
matrix.hpp:30:46: error: expected primary-expression before ‘...’ token
     T & operator()(size_t idx, Indexes&& ... indexes) 
                                          ^
matrix.hpp:30:57: error: declaration of ‘operator()’ as non-function
     T & operator()(size_t idx, Indexes&& ... indexes) 
                                                     ^
matrix.hpp:39:29: error: ‘size_t’ was not declared in this scope
     T const& operator()(size_t idx, Indexes&& ... indexes) const 
                         ^
matrix.hpp:39:48: error: expected primary-expression before ‘&&’ token
     T const& operator()(size_t idx, Indexes&& ... indexes) const 
                                            ^
matrix.hpp:39:51: error: expected primary-expression before ‘...’ token
     T const& operator()(size_t idx, Indexes&& ... indexes) const 
                                               ^
matrix.hpp:39:62: error: declaration of ‘operator()’ as non-function
     T const& operator()(size_t idx, Indexes&& ... indexes) const 
                                                          ^
matrix.hpp:70:9: error: ‘size_t’ does not name a type
     size_t dimension_size(size_t dim) const {
     ^
matrix.hpp:74:9: error: ‘size_t’ does not name a type
     size_t num_of_dimensions() const {
     ^
matrix.hpp:80:9: error: ‘size_t’ does not name a type
     size_t apply_dimensions(size_t dim, Dimensions&& ... dims)
     ^
matrix.hpp:86:9: error: ‘size_t’ does not name a type
     size_t apply_dimensions(size_t dim) 
     ^
matrix.hpp:93:9: error: ‘size_t’ does not name a type
     size_t get_flat_index(size_t dim, size_t index, Indexes&& ... indexes) 
     ^
matrix.hpp:98:9: error: ‘size_t’ does not name a type
     size_t get_flat_index(size_t dim, size_t index) const 
     ^
matrix.hpp:103:9: error: ‘size_t’ does not name a type
     size_t get_offset(size_t index, size_t dim) const 
     ^
matrix.hpp:114:12: error: expected ‘;’ at end of member declaration
     T& at(size_t flat_index) {
        ^
matrix.hpp:114:22: error: expected ‘)’ before ‘flat_index’
     T& at(size_t flat_index) {
                  ^
matrix.hpp:118:18: error: expected ‘;’ at end of member declaration
     T const& at(size_t flat_index) const {
              ^
matrix.hpp:118:21: error: redeclaration of ‘const T& Matrix<T>::at’
     T const& at(size_t flat_index) const {
                 ^
matrix.hpp:114:15: note: previous declaration ‘T& Matrix<T>::at’
     T& at(size_t flat_index) {
           ^
matrix.hpp:118:28: error: expected ‘)’ before ‘flat_index’
     T const& at(size_t flat_index) const {
                        ^
matrix.hpp:122:9: error: ‘size_t’ does not name a type
     size_t flat_size() const {
     ^
matrix.hpp: In function ‘void swap(Matrix<T>&, Matrix<T>&)’:
matrix.hpp:64:24: error: ‘std::swap’ has not been declared
         using std::swap;
                    ^
In file included from test.cpp:1:0:
test.hpp: At global scope:
test.hpp:8:28: error: ‘NULL’ was not declared in this scope
 Matrix<double>* temp = NULL;
                        ^
test.cpp: In constructor ‘Test::Test()’:
test.cpp:5:33: error: no matching function for call to ‘Matrix<double>::Matrix(<brace-enclosed initializer list>)’
 mat = Matrix<double>{9, 2, 8};
                             ^
In file included from test.hpp:3:0,
             from test.cpp:1:
matrix.hpp:50:9: note: candidate: Matrix<T>::Matrix(Matrix<T>&&) [with T = double]
     Matrix(Matrix&& other)
     ^
matrix.hpp:50:9: note:   candidate expects 1 argument, 3 provided
matrix.hpp:47:9: note: candidate: Matrix<T>::Matrix(const Matrix<T>&) [with T = double]
     Matrix(const Matrix&) 
     ^
matrix.hpp:47:9: note:   candidate expects 1 argument, 3 provided
matrix.hpp:12:9: note: candidate: Matrix<T>::Matrix() [with T = double]
     Matrix() 
     ^
matrix.hpp:12:9: note:   candidate expects 0 arguments, 3 provided
matrix.hpp: In instantiation of ‘Matrix<T>::Matrix() [with T = double]’:
test.cpp:3:12:   required from here
matrix.hpp:12:9: error: uninitialized reference member in ‘double&’ [-fpermissive]
matrix.hpp:114:15: note: ‘double& Matrix<double>::at’ should be initialized
     T& at(size_t flat_index) {

据我所知,识别模板类型存在问题,但我不知道如何解决。最后,我想说的是我在另一个类之外使用矩阵类没有任何问题。例如,以下代码似乎工作正常。

#include <iostream>
#include <memory>
#include "fcontainer.hpp"
#include "printer.hpp"
#include "matrix.hpp"
#include "test.hpp"
using namespace std;

int main(int argc, char *argv[])
{
    std::cout << "Input the sizes of each of the dimensions.\n";
    std::string line;
    std::getline(std::cin, line);
    std::stringstream ss(line);
    size_t dim;
    std::vector<size_t> dimensions;
    while(ss >> dim)
        dimensions.emplace_back(dim);
    Matrix<double> mat{6, 5};
    mat(5, 2) = 17;
    Matrix<double>* temp = NULL;
    mat = Matrix<double>{9, 2, 8};
    temp = &(mat);
    mat(5, 1, 7) = 24;
    cout << mat(5, 1, 7) << endl;
    cout << (*temp)(5, 1, 7) << endl;
    return 0;
}

所以我想了解课程中出了什么问题以及我能做些什么来解决它。

1 个答案:

答案 0 :(得分:1)

正如@Oliv和@AndyG所说,你需要为依赖项添加#include

#include <vector>
#include <memory>

您应该在定义Matrix之前包含它们。一种方法是在#include中移动Test.hpp语句,但更好的方法是将它们添加到Matrix.hpp的开头,以便矩阵头文件是自包含的。