首页 > 解决方案 > 漏洞?当数组具有模板大小时,为什么我不能在数组成员上使用模板函数

问题描述

问题

这是我经历过的最奇怪的事情。3小时后,我设法将其归结为这个可重现的示例(下面的代码,如果有点乱,对不起,我尽力了)

我用评论标记了这一行。请不要,上面的一行不是问题。我还为 Test 结构提供了一些其他定义。如果我替换 MWE 中提供的那个,那么它可以完美地编译。最值得注意的是,我可以分配weights[0]A然后调用A.applyFunction<float>(...). 那么 g++ 是什么原因,它不喜欢我的数组元素呢?我首先想到,这可能是由于模板大小,事实上,如果我用固定大小替换它,它就会编译。但是, thenA=weights[0]也不应该工作。我真的很好奇,会有什么解释。

错误信息

g++ -o test -c test.cpp -O0 -ggdb -DDEBUG -D__DEBUG -Wextra -Wshadow -Wconversion -Werror -Wall  
test.cpp: In constructor ‘Test<sz>::Test()’:  
test.cpp:79:43: error: expected primary-expression before ‘float’  
   79 |     weights[0] = weights[0].applyFunction<float>(test);  
      |                                           ^~~~~  
test.cpp:79:43: error: expected ‘;’ before ‘float’
   79 |     weights[0] = weights[0].applyFunction<float>(test); 

编译器信息:

g++ --version g++ (Ubuntu 9-20190428-1ubuntu1~18.04.york0) 9.0.1 20190428 (prerelease) [gcc-9-branch revision 270630] 版权所有 (C) 2019 Free Software Foundation, Inc. 这是免费软件;查看复制条件的来源。没有保修;甚至不考虑适销性或特定用途的适用性。

代码

#include <algorithm>
#include <array>
#include <cstdio>
#include <functional>
#include <iostream>
#include <iterator>
#include <ostream>
#include <stdexcept>

namespace Math{
  template<typename R>
  struct Matrix{
  private: unsigned short nRows, nCols;
  public:
    R* data;
    Matrix<R>() : nRows(0), nCols(0){}
    Matrix<R>(unsigned short nRows_, unsigned short nCols_) : Matrix<R>(nRows_, nCols_, R{}){
    }
    Matrix<R>(unsigned short nRows_, unsigned short nCols_, const R& val) : nRows(nRows_),nCols(nCols_){
      data = new R[nRows * nCols];
      for( unsigned short i = 0; i < nRows; ++i ){
        for( unsigned short j = 0; j < nCols; ++j ){
          data[i*nCols+j] = val;
        }
      }
    }
    Matrix<R>(unsigned short nCols_, unsigned short nRows_, R* vals) : nRows(nRows_), nCols(nCols_){
      data = new R[nRows * nCols];
      std::copy(vals, vals+nRows*nCols, data);
    }
    ~Matrix<R>(){
      delete[] data;
    }
    Matrix<R>(const Matrix<R>& m) : nRows(m.nRows), nCols(m.nCols){
      data = new R[nRows * nCols];
      data = m.data;
    }
    Matrix<R>& operator=(const Matrix<R>& m){
        nRows = m.getNumRows();
        nCols = m.getNumCols();
        data = new R[nRows * nCols];
        std::copy(m.data, m.data+nRows*nCols, data);
        return *this;
    }

    template<typename S>
    Matrix<S> applyFunction(std::function<S(R)> f){
      Matrix<S> result(nCols, nRows);
      for( unsigned short i = 0; i < nRows; ++i ){
        for( unsigned short j = 0; j < nCols; ++j ){
          result.data[i*nCols+j] = f(data[i*nCols+j]);
        }
      }
      return result;
    }
    unsigned short getNumCols() const{
      return nCols;
    }
    unsigned short getNumRows() const{
      return nRows;
    }
  };
}

float test(float x){return x*x;}

using Math::Matrix;

template<unsigned short sz>
struct Test{
  std::array<Matrix<float>, sz+1> weights;

  Test(){

    Matrix<float> A;
    A = Matrix<float>(2, 2, 0.132f);
    weights[0] = Matrix<float>(2, 2, 0.132f);
    A = A.applyFunction<float>(test);
    weights[0] = weights[0].applyFunction<float>(test); /* Line 79 */
  }
};

int main(){
  Test<2> t;
}

测试#2(有效)

template<unsigned short sz>
struct Test{
  std::array<Matrix<float>, sz+1> weights;

  Test(){

    Matrix<float> A;
    A = Matrix<float>(2, 2, 0.132f);
    weights[0] = Matrix<float>(2, 2, 0.132f);
    A = weights[0];
    A = A.applyFunction<float>(test);
//    weights[0] = weights[0].applyFunction<float>(test);
  }
};

测试#3(有效)

template<unsigned short sz>
struct Test{
  std::array<Matrix<float>, 3> weights;

  Test(){

    Matrix<float> A;
    A = Matrix<float>(2, 2, 0.132f);
    weights[0] = Matrix<float>(2, 2, 0.132f);
    A = A.applyFunction<float>(test);
    weights[0] = weights[0].applyFunction<float>(test);
  }
};

标签: c++arraystemplates

解决方案


推荐阅读