c++ - 为 double 和 std::complex 创建不需要特化的函数模板
问题描述
作为一项学习练习,我试图创建一个就地计算 Hermitian 共轭的函数。当所有条目都是真实的时,它应该表现得像一个简单的转置,因此应该与 double 一起使用。我知道我可以单独专门针对双精度,并且在这个特定示例中是可行的。但是,我认为对于像 ODE 求解器这样的大型问题,专业化会变得乏味。
我尝试了以下
#include <complex>
const size_t ZERO = 0ul;
template <class value_type,
class container_type = value_type*>
auto
hermitianConjugate(container_type buffer, size_t width)
{
for (size_t row = ZERO; row < width; row++)
{
for (size_t col = ZERO; col < width; col++)
{
auto temp = std::conj(buffer[col * width + row]);
if (std::imag(temp) == 0)
{
// works for both double and std::complex
buffer[row * width + col] = buffer[col * width + row];
} else
{
// for std::complex
buffer[row * width + col] = temp;
// raises error when value_type is double
}
}
}
}
是否有不涉及明确专业化的解决方法?如果有意义的话,有什么方法可以“静态地”使用条件分支?
解决方案
if-constexpr
如果你有 c++17,你可以使用。这本质上创建了不同的专业化,而无需编写单独的函数。
#include <complex>
#include <type_traits>
const size_t ZERO = 0ul;
template <class value_type,
class container_type = value_type*>
auto
hermitianConjugate(container_type buffer, size_t width)
{
for (size_t row = ZERO; row < width; row++)
{
for (size_t col = ZERO; col < width; col++)
{
if constexpr (std::is_same_v<value_type, std::complex<double>>) {
// only for complex
buffer[row * width + col] = std::conj(buffer[col * width + row]);
}
else
{
// for double
buffer[row * width + col] = buffer[col * width + row];
}
}
}
}
如果您没有 c++17,您可以编写一个重载函数来执行不同的任务,具体取决于类型:
#include <complex>
const size_t ZERO = 0ul;
constexpr double myconj(double x) noexcept { return x; }
std::complex<double> myconj(std::complex<double> x) { return std::conj(x); }
template <class value_type,
class container_type = value_type*>
auto
hermitianConjugate(container_type buffer, size_t width)
{
for (size_t row = ZERO; row < width; row++)
{
for (size_t col = ZERO; col < width; col++)
{
buffer[row * width + col] = myconj(buffer[col * width + row]);
}
}
}
请注意,std::conj已经为 double 提供了专用重载,但在这种情况下,它也返回 a std::complex
。
推荐阅读
- c# - 根据暂存环境更改文件位置
- python - 如何将用户输入从前端(即 HTML 表单)附加到 url
- git - git cherry-pick 如何计算补丁?
- python - pyparsing范围解析整数字节表示
- api - HttpClient 未将发布数据发送到 NancyFX 端点
- python-3.x - 在奥赛罗棋盘游戏中使用时,windows python 子进程将不起作用
- javascript - 使用 Twitter Typeahead.js 的多个远程源
- node.js - ModuleBuildError:模块构建失败:TypeError [ERR_INVALID_ARG_TYPE]:“路径”参数必须是字符串类型。接收类型未定义
- python - 为列表 Python 上的奇数加 1
- xcode - 将 macOS 更新到 Catalina 后,无法在 Xcode 中构建 React Native 项目