2017-04-16 135 views
2

我为T类型的矩阵创建了一个矩阵模板类。我收到一个链接器错误和一条警告:Instantiation of variable 'ndmatrix<unsigned int>::Subscriptable::_data' required here, but no definition is availableC++ template:'Instantiation of variable required,but no definition is'

ndmatrix.h: 
#ifndef ndmatrix_h 
#define ndmatrix_h 
#include <vector> 
#include <functional> 
#include <algorithm> 

//Generic matrix class to hold the table levels of type T 
template<class T> 
class ndmatrix{ 

public: 

    size_t R; //rows 
    size_t C; //cols 

    //Hack to use [][] operator on std::vector 
    class Subscriptable{ 
    public: 

     //Default constructor 
     Subscriptable(){}; 

     Subscriptable(int idx, size_t R, size_t C) : _idx(idx), _R(R), _C(C) { 
      for (int i = 0; i<_C*_R; i++) { 
       _data.push_back(0); 
      } 
     }; 

     Subscriptable setIdx(int i){ 
      this->_idx = i; 
      return *this; 
     } 

     //This is [] operator for ndmatrix::Subscriptable 
     T operator[](int index) { 
      return _data[_C *_idx + index]; 
     } 

     auto addElement(T e, int i, int j){ 
      return _data.insert(_data.begin() + _C*i + j, e); 
     }; 

     auto data() { return _data; }; 
    private: 
     size_t _R; //rows 
     size_t _C; //cols 
     int _idx; 
     static std::vector<T> _data; <== Warning: Instantiation of variable 'ndmatrix<unsigned int>::Subscriptable::_data' required here, but no definition is available. 
    }; 

    Subscriptable _s; 

    //This is [] operator for ndmatrix 
    Subscriptable operator[](int idx){ 
     return _s.setIdx(idx); 
    }; 

    //Constructors 
    ndmatrix(); 
    ndmatrix(int __C, int __R); 

    //Member functions 
    void addRow(std::vector<T> row); 
    void print_to_console(std::function<void(T)> printer); //printer is used to print one element of type T to the console. 
}; 

template <class T> 
ndmatrix<T>::ndmatrix(){ 
    _s = Subscriptable(); 
}; 

template <class T> 
ndmatrix<T>::ndmatrix(int __C, int __R){ 
    _s = Subscriptable(); 
    for (int i=0; i<__C*__R; i++) { 
     _s.push_back(0); 
    } 
}; 

template <class T> 
void ndmatrix<T>::addRow(std::vector<T> row){ 
    this->_s.data().insert(_s.data().end() , row.begin(), row.end()); 
}; 

template <class T> 
void ndmatrix<T>::print_to_console(std::function<void(T)>printer) { 
    for(int i=0; i<R; i++){ 
     std::cout << std::endl; 
     for (int j=0; j<C; j++) { 
      printer((*this)[i][j]); 
     } 
    } 
} 

#endif /* ndmatrix_h */ 

然后我尝试在main.cpp:

#include <iostream> 
#include <fstream> 
#include <sstream> 
#include "ndmatrix.h" 

typedef unsigned int level_t; 


//Read table of levels from file into a matrix 
void read_matrix(ndmatrix<level_t>* const mat, const char* filename){ 
    std::ifstream fileInput(filename); 

    int rows = 0; 
    while (fileInput) { 
     std::string line; 
     std::getline(fileInput, line, '\n'); 

     std::stringstream strstream(line); 
     std::vector<level_t> row; 
     level_t level; 
     int cols=0; 
     while (strstream >> level) { 
      row.push_back(level); 
      cols++; 
     } 

     mat->addRow(row); 
     rows++; 

     mat->C = cols; 
     mat->R = rows; 

     //debug 
     std::cout << line << std::endl; 
    } 
}; 

int main(int argc, const char * argv[]) { 

    //tests 
    ndmatrix<level_t> matrix; 
    read_matrix(&matrix, "table.dat"); 

    // insert code here... 
    std::cout << "Hello, World!\n"; 
    return 0; 
} 

使用这个当试图建立我得到上面的警告,然后:

模板是在一个单独的头文件中定义一个链接器错误:

clang: error: linker command failed with exit code 1 (use -v to see invocation) 

回答

3

你已经写了静态成员变量_data的声明,但是跳过了定义。

template< typename T > typename ::std::vector<T> ndmatrix<T>::Subscriptable::_data; 
+0

如果我添加'模板类型名称::的std ::矢量< T > ndmatrix < T > ::标化的:: _数据;'然后它工作。 (你忘了:: Subscriptable :))。但我真的不明白,为什么我需要这个? –

+1

您需要这样做是因为类定义只能包含静态变量声明(除了const enum或const整型)。而为了使用这个变量,你需要将定义放在类范围之外的某个地方。这些规则很奇怪。 – VTT

相关问题