首页 > 解决方案 > 乘以 std::complex通过模板化运算符重载加倍

问题描述

假设已定义,我想将 a 与 a 进行多重播放std::complex<T>。由于我需要为 3 种不同的类型执行此操作,因此我尝试为操作员编写模板函数。这是一个例子。doubleT operator*(const T &t, double d)TT=float

#include <iostream>
#include <complex>

template <typename T>
std::complex<T> operator*(const std::complex<T> &cd, double d) {
    return std::complex<T>(cd.real() * d, cd.imag());
}

int main() {
    std::complex<float> cf(1.0, 1.0);
    std::complex<double> cd(1.0, 1.0);
    double d = 2.0;

    std::cout << cf * d << std::endl;
    std::cout << cd * d << std::endl;
}

这会导致编译器错误

error: ambiguous overload for ‘operator*’ (operand types are ‘std::complex<double>’ and ‘double’)

原因很清楚,因为T=double我的重载与<complex>. 首先将右侧转换为 a T(即cf * float(d)在上面的示例中)不是一种选择,因为这会给我的一些数据类型带来很大的开销。

有什么办法可以告诉编译器它应该忽略我的重载T=double吗?

标签: c++templatesoperator-overloadingstdoperator-keyword

解决方案


std::complex已经定义了一个operator *形式的

template< class T >
std::complex<T> operator*( const std::complex<T>& lhs, const T& rhs);

这与您自己的冲突,operator *因为这两个函数都解析为采用 astd::complex<double>和 a double

这意味着你真的只需要定义一个operator *forstd::vector<float>和 adouble这样你就可以将你的重载更改为

std::complex<float> operator*(const std::complex<float> &cd, double d) {
    return std::complex<float>(cd.real() * d, cd.imag());
}

接着

std::cout << cf * d << std::endl;
std::cout << cd * d << std::endl;

将工作。

如果您想将重载保留为模板函数,您可以使用 SFINAE 使其无法在您有 a 的情况下std::complex<double>编译

template <typename T, std::enable_if_t<!std::is_same_v<double, T>, bool> = true>
std::complex<T> operator*(const std::complex<T> &cd, double d) {
    return std::complex<T>(cd.real() * d, cd.imag());
}

推荐阅读