我试图通过使用容器使两种类型的对象兼容,为了使其更困难,我的代码必须能够在编译时进行计算。
我的一个对象类型按以下方式构造为函子:
template <std::size_t n,std::size_t p=1,typename number=double>
class Oper{
public:
constexpr Oper(const number d_=1.):d(d_){}
constexpr Oper(const Oper& oper_):d(oper_.d){}
const number d ;
constexpr auto operator()(const auto &v) const {
typename std::remove_const<typename std::remove_reference<decltype(v)>::type>::type w{} ;
/* Do some stuff to build w using v and d*/
return w ;}
};
另一种对象类型只是
std::array<std::array<double,n>,n>
,即矩阵。
这些对象具有以下作为自由函数的运算符:
template <std::size_t nr, std::size_t nc>
constexpr auto
operator *(const std::array<std::array<double,nc>,nr> & A,
const std::array<double,nc> & x){
std::array<double,nr> res{};
for (auto i=0u;i<nr;i++)
for (auto j=0u;j<nc;j++)
res[i] += A[i][j]*x[j];
return res;
}
template <std::size_t nrA, std::size_t ncA, std::size_t nrB, std::size_t ncB>
constexpr auto operator *(const std::array<std::array<double,ncA>,nrA> & A,
const std::array<std::array<double,ncB>,nrB> & B){
std::array<std::array<double,ncB>,nrA> res{};
for (auto k=0u;k<ncB;++k)
for (auto i=0u;i<nrA;++i)
for (auto j=0u;j<nrB;++j)
res[i][k] += A[i][j]*B[j][k];
return res ;
}
constexpr auto operator *(const auto & A,const auto & x){
return A(x) ;
}
请记住,我无法更改这些实现,它们是提供给我的。
为了使这些操作符兼容,我创建了以下类
constexpr auto id = [](const auto v) {return v;};
template <typename Op, typename Preop=decltype(id)>
class Cont{
public:
constexpr Cont(const Op & op_,const Preop & preop_=id):op(op_),preop(preop_){}
constexpr Cont(const Cont & cont_):op(cont_.op),preop(cont_.preop){}
const Op op ;
const Preop preop ;
template <typename Op2, typename Preop2>
constexpr auto operator()(const Cont<Op2,Preop2> & mfop) const{
return Cont<const Cont<Op,Preop>,const Cont<Op2,Preop2>>
(Cont(op,preop),mfop);}
constexpr auto operator()(const auto & v) const{return op*(preop*v);}
};
这样,下面的主要代码就可以按预期编译和运行了
int main(){
const std::array<double,4> v{};
const Cont A(Oper<4,1>(1.));
const Cont B(std::array<std::array<double,4>,4>{std::array<double,4>{}});
constexpr auto res = B*B*A*A*B*A*B*v;
return 0;
}
门闩示例
here
.
我对这个问题有意见
Cont
班
-
关于
继续
当只使用函子(不使用数组)时,就是以某种方式将对应于不同函子的代码一个接一个地放置,理想情况下,优化整个链。这能实现吗?我该怎么做?也许是完美的转发魔法?
-
有许多复制品正在制作中
继续
,这会导致编译器占用大量内存(GCC 8.2.0,带标志)
-std=c++1z -fconcepts -Ofast
)当要求进行完整的编译时计算时。我相信这是因为所有的拷贝都是在把操作员放在一起时执行的。这可能吗?有没有办法避免复制?