2017-09-18 5 views
1

Vor ein paar Wochen fragte ich diese question über eine "variadic" Matrix-Klasse und jetzt versuche ich, die Antwort in einem anderen Projekt anzuwenden, und ich bekomme Fehler, die ich nicht verstehe. Im Grunde ist das Problem, dass ich nicht verstehe, wie man die "variadic" -Matrixklasse als Attribut in einer anderen Klasse verwendet (die im minimalen Arbeitsbeispiel Test genannt wird).Verwenden variadic Vorlage als Attribut

Minimal Arbeits Beispiel 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}; 
} 

Nach dem Kompilieren mit "g ++ -std = C++ 14 * CPP -o cfd.out", ich die folgende Art von Fehlermeldungen erhalten:

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) { 

So weit ich es verstehe, gibt es ein Problem beim Erkennen des Vorlagentyps, aber ich weiß nicht, wie ich es lösen soll. Schließlich möchte ich bemerken, dass ich keine Probleme mit der Verwendung der Matrix-Klasse außerhalb einer anderen Klasse hatte. Zum Beispiel scheint das folgende Stück Code gut zu funktionieren.

#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; 
} 

Also ich würde gerne verstehen, was in einer Klasse schief geht und was ich kann, es zu lösen tun.

+5

Haben Sie nicht vergessen, #include ?? – Oliv

+0

Fügen Sie auch '#include ' zu Ihrer .hpp-Datei hinzu. Im Allgemeinen fehlt diese Datei includes. – AndyG

+0

@Oliv Ich habe tatsächlich vergessen #include und #include in diesem Testfall. Hinzugefügt sie, aber änderte das Problem nicht. Wird die Frage aktualisieren. –

Antwort

1

Als @Oliv und @AndyG sagte, müssen Sie #include für die Abhängigkeiten hinzuzufügen:

#include <vector> 
#include <memory> 

Sie sollten sie enthalten vor Matrix definiert ist. Eine Möglichkeit dazu besteht darin, die #include-Anweisungen früher in Test.hpp zu verschieben, aber noch besser ist es, sie zum Anfang von Matrix.hpp hinzuzufügen, sodass die Matrix-Header-Datei eigenständig ist.

Verwandte Themen