C++中重载乘法运算符的递归类模板实例化过程中出错



我正在尝试为一个非常特殊的盒子实现一个模板类,称为H box
它包含一个大小始终为2的幂的数字向量。本质上就是这样,当涉及到结构时——它只包含一个数组,并且重载了[]运算符来访问其元素。问题是-它有一个非常奇特的乘法规则:两个H盒的乘积归结为向左拆分向量-&右半,创建较小的方框,将它们交叉相乘,最后将结果相加(详细信息见下面的代码(。因此,问题是乘法运算符被重载为递归函数,它会生成越来越小的框。

我已经让代码为我的类的非模板版本工作了。然而,在我移动到模板后,我无法正确处理它。。。

template <typename T, const unsigned int size>
HBox<T, size> operator*(
const HBox<T, size> &H1,
const HBox<T, size> &H2
) {
// recursion base:
if (size == 1) {
T temparr[] = { H1[0] * H2[0] };
HBox<T, 1> H_(temparr);
return H_;
}
// shared objects:
const unsigned int halfsize = size / 2;
T* temparr = new T[size];
// construct helper objects:
for (unsigned int i=0; i < halfsize; i++) temparr[i] = H1[i];
HBox<T, halfsize> H1a(temparr);
for (unsigned int i=0; i < halfsize; i++) temparr[i] = H1[i+halfsize];
HBox<T, halfsize> H1b(temparr);
for (unsigned int i=0; i < halfsize; i++) temparr[i] = H2[i];
HBox<T, halfsize> H2a(temparr);
for (unsigned int i=0; i < halfsize; i++) temparr[i] = H2[i+halfsize];
HBox<T, halfsize> H2b(temparr);
// multiply recursively:
HBox<T, halfsize> H1a2a = H1a * H2a;
HBox<T, halfsize> H2b1b = H2b * H1b;
HBox<T, halfsize> H2b1a = H2b * H1a;
HBox<T, halfsize> H1b2a = H1b * H2a;
// construct the final object
HBox<T, halfsize> Ha = H1a2a + H2b1b;
HBox<T, halfsize> Hb = H2b1a + H1b2a;
for (unsigned int i=0; i < halfsize; i++) temparr[i] = Ha[i];
for (unsigned int i=0; i < halfsize; i++) temparr[i+halfsize] = Hb[i];
HBox<T, size> H(temparr);
delete[] temparr;
return H;
}

我编译了一个简单的测试程序,其中包含两个四元素float框(A * B(与的乘积

Run g++ -O0 -Wall --std=c++14 -o test test.cpp

我得到以下错误:

In file included from test.cpp:17:
HBox/HBox.hpp: In instantiation of ‘HBox<T, size> operator*(const HBox<T, size>&, const HBox<T, size>&) [with T = float; unsigned int size = 4]’:
test.cpp:266:44:   required from here
HBox/HBox.hpp:276:16: error: could not convert ‘H_’ from ‘HBox<[...],1>’ to ‘HBox<[...],4>’
276 |         return H_;
|                ^~
|                |
|                HBox<[...],1>
Error: Process completed with exit code 1.

出了什么问题?在我看来,这里应该一切都很好。。。

使用模板递归时,不能将基本情况提供为简单的if。这样做的原因是,即使某些代码无法访问,整个函数也需要能够编译。一个简单的if (false)是不够的。

要解决此问题,您可以使用C++17的if constexpr或部分模板专用化:

// using if constexpr
template <typename T, const unsigned int size>
HBox<T, size> operator*(
const HBox<T, size> &H1,
const HBox<T, size> &H2
) {
if constexpr (size == 1) {
// handle base case here
} else {
// handle recursive case here
}
}

// using partial template specialization
template <typename T, const unsigned int size>
HBox<T, size> operator*(
const HBox<T, size> &H1,
const HBox<T, size> &H2
) {
// handle recursive case here
}
template <typename T>
HBox<T, 1> operator*<T, 1>( // partial specialization for size == 1
const HBox<T, 1> &H1,
const HBox<T, 1> &H2
) {
// handle base case here
}

即使您的程序在n!=1您的编译器正试图编译这样的分支。所以您可以从必须返回HBox<T, 4>的函数中返回HBox<T, 1>。首先尝试将constexpr添加到if

if constexpr (size == 1)...

如果它没有帮助,尝试使用这个代码

HBox<T, size> operator*(const HBox<T, size> &H1, const HBox<T, size> &H2);
template <typename T>
HBox<T, 1> operator*(const HBox<T, 1> &H1, const HBox<T, 1> &H2) {
T temparr[] = {H1[0] * H2[0]};
HBox<T, 1> H_(temparr);
return H_;
}
template <typename T, const unsigned int size>
HBox<T, size> operator*(const HBox<T, size> &H1, const HBox<T, size> &H2) {
// shared objects:
const unsigned int halfsize = size / 2;
T *temparr = new T[size];
// construct helper objects:
for (unsigned int i = 0; i < halfsize; i++) temparr[i] = H1[i];
HBox<T, halfsize> H1a(temparr);
for (unsigned int i = 0; i < halfsize; i++) temparr[i] = H1[i + halfsize];
HBox<T, halfsize> H1b(temparr);
for (unsigned int i = 0; i < halfsize; i++) temparr[i] = H2[i];
HBox<T, halfsize> H2a(temparr);
for (unsigned int i = 0; i < halfsize; i++) temparr[i] = H2[i + halfsize];
HBox<T, halfsize> H2b(temparr);
// multiply recursively:
HBox<T, halfsize> H1a2a = H1a * H2a;
HBox<T, halfsize> H2b1b = H2b * H1b;
HBox<T, halfsize> H2b1a = H2b * H1a;
HBox<T, halfsize> H1b2a = H1b * H2a;
// construct the final object
HBox<T, halfsize> Ha = H1a2a + H2b1b;
HBox<T, halfsize> Hb = H2b1a + H1b2a;
for (unsigned int i = 0; i < halfsize; i++) temparr[i] = Ha[i];
for (unsigned int i = 0; i < halfsize; i++) temparr[i + halfsize] = Hb[i];
HBox<T, size> H(temparr);
delete[] temparr;
return H;
}```

相关内容

最新更新