C++ 当使用对象执行算术运算时,隐式地将其转换为浮点类型

C++ 当使用对象执行算术运算时,隐式地将其转换为浮点类型,c++,c++11,implicit-conversion,C++,C++11,Implicit Conversion,假设我们有一个全局对象pi,并希望根据上下文将其隐式转换为float或double。以下操作不起作用: #include <cmath> class Pi { public: Pi() {} operator float() const { return std::atan(1.0f)*4.0f; } operator double() const { return std::atan(1.0)*4.0;

假设我们有一个全局对象
pi
,并希望根据上下文将其隐式转换为
float
double
。以下操作不起作用:

#include <cmath>

class Pi {
public:
    Pi() {}

    operator float() const {
        return std::atan(1.0f)*4.0f;
    }

    operator double() const {
        return std::atan(1.0)*4.0;
    }
};

const Pi pi;

#include <iostream>
#include <iomanip>

int main() {
    std::cout << std::setprecision(50) << pi * 1.0f << std::endl;
    std::cout << std::setprecision(50) << pi * 1.0  << std::endl;
}

或者你能想出一个更优雅的解决方案来隐式地将全局对象转换为适合上下文的类型吗?

你的第一次尝试就要成功了。让我们在类之外添加一个模板化的
*
运算符:

template<typename T>
T operator*(const Pi& pi, T&& other)
{
    return static_cast<T>(pi) * std::forward<T>(other);
}
模板
T运算符*(常数π和π,T和其他)
{
返回静态(pi)*标准::正向(其他);
}
现在它开始工作了


完整代码
#包括
#包括
#包括
Pi类{
公众:
Pi(){}
运算符float()常量{
返回标准::atan(1.0f)*4.0f;
}
运算符double()常量{
返回标准::atan(1.0)*4.0;
}
};
常数Pi;
模板
T运算符*(常数π和π,T和其他)
{
返回静态(pi)*标准::正向(其他);
}
int main(){

老实说,我只会选择最不出人意料的方式:

class Pi {
    ...
    explicit operator float() { ... }
    explicit operator double() { ... }
    ...
};
只要在你想要的时候投下它:

std::cout << std::setprecision(50) << (float)pi * 1.0f << std::endl;

std::cout根据上下文的不同,最优雅的解决方案可能是对代码维护人员来说最容易混淆的解决方案。因此,与其依赖魔术,不如使用显式as_float和as_double方法。您可以在操作符中使用模板,因此不需要编写每一个操作符:
template t operator*(t x)const{return(std::atan(T{1})*T{4})*x;}
BTW,你真的需要
float
version,是不是
double
还不够?是的,我真的需要
float
double
version。你说的变量是什么意思?@user1225999的意思是,只是用了错误的词。但是我必须写
pi()
?@user1225999没有。只要
pi
pi()
就会被称为名为
pi
的函数模板。
class Pi {
    ...
    explicit operator float() { ... }
    explicit operator double() { ... }
    ...
};
std::cout << std::setprecision(50) << (float)pi * 1.0f << std::endl;