【问题标题】:multidimensional array template class with expression templates带有表达式模板的多维数组模板类
【发布时间】:2018-11-04 19:53:48
【问题描述】:

我试图通过实现我自己的多维数组类来理解表达式模板。基本上,我分配一个连续的内存块,然后使用 () 运算符计算偏移量。

现在我想用表达式模板重载 +,/,*,-。 wikipedia 中的示例非常具有说明性,但它假设数据块是 double 类型。我想将数据类型作为模板参数。我试图实现这一点,但我总是失败。这是到目前为止的代码:

    namespace ader{

    template<class E, typename T> class vexp{
        inline unsigned size()const{return static_cast<E const&>(*this).size();};
        inline T operator[](const unsigned &i) const{ return static_cast<E const&>(*this)[i];}
    };

// ***************************************************************************** // 

    template<class E1, class E2, typename T>
        class vsum:
        public vexp<vsum<E1,E2,T>,T>{
        const E1 &_u;
        const E2 &_v;
        public:
        vsum(const E1 &u, const E2 &v): _u(u), _v(v){};
        inline T operator[](const unsigned &i)const {return _u[i] + _v[i];};
        inline unsigned size()const{return _u.size();};
    };


// ***************************************************************************** // 


    template<typename T, unsigned nDer> class aDer: public ader::vexp<aDer<T,nDer>,T>{
        protected:
        unsigned n;
        T d[nDer+1];

        public:
        unsigned size()const{return n;};

        T  operator[](const unsigned &i)     {return d[i];};
        T &operator[](const unsigned &i)const{return d[i];};

        aDer():n(nDer), d{0}{};
        aDer(const T &in): n(nDer), d{0}{d[0] = in;};
        aDer(const T &in, const unsigned &idx): n(nDer), d{0}{d[0] = in; d[idx+1] = T(1);};
        template<template<typename,unsigned> class U> aDer(const vexp<U<T,nDer>,T> &in){
            for(unsigned ii=0; ii<=nDer; ++ii) d[ii] = in[ii];
        }
    };

    template< class E1, class E2, typename T>
        vsum<E1,E2,T> operator+(const E1 &u, const E2 &v){return vsum<E1,E2,T>(u,v);};


};

错误信息:

main2.cc: In function ‘int main()’:
main2.cc:15:27: error: no match for ‘operator+’ (operand types are ‘ader::aDer<float, 2>’ and ‘ader::aDer<float, 2>’)
ader::aDer<float,2> c= a+b;

代码中有什么明显的错误吗?

EDIT1:main2.cc的内容:

#include "aut2.h"
#include <iostream>

using namespace std;

int main(){

    ader::aDer<float,2> a(1.220334, 1);
    ader::aDer<float,2> b(3.0, 0);

    ader::aDer<float,2> c= a+b;

    cerr<<c[0]<<endl;

}

【问题讨论】:

  • 询问时,请提供完整代码sn-ps(我们可以编译重现错误)和完整错误信息。
  • 除了您发布的错误消息外,我的 GCC 还说 note: candidate: 'blah blah' note: couldn't deduce template parameter 'T'。由于operator+的参数不依赖于T,所以无法推断。您可能可以改用const vexp&lt;E1,T&gt; &amp;u, const vexp&lt;E2,T&gt; &amp;v 作为参数。这修复了no match for ‘operator+’,但揭示了一些其他错误。

标签: c++ c++11 templates lazy-evaluation


【解决方案1】:

您的operator+ 有一个不可推导的参数T。你需要去掉这个参数,从E1E2推断T

实现这一目标的一种方法是像这样定义您的operator+

template <class E1, class E2>
auto operator+(const E1 &u, const E2 &v) -> vsum<E1, E2, decltype(u[0] + v[0])>
{
    return { u,v };
}

另一种方法是使用autodecltype(auto) 来完全摆脱所有类中的T 参数:

template <class E> class vexp {
    ...
    inline decltype(auto) operator[](const unsigned &i) const { return static_cast<E const&>(*this)[i]; }
};

在上面的代码中,operator[] 将返回 E::operator[] 返回的任何类型。

请注意,没有尾随返回类型规范的 decltype(auto)auto 是 C++14 功能。

【讨论】:

  • 谢谢!在 vexp 和 vsum 中使用 decltype(auto) 就可以了。
猜你喜欢
  • 1970-01-01
  • 2014-01-02
  • 1970-01-01
  • 2011-08-25
  • 2023-03-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-03-05
相关资源
最近更新 更多