将运算符类型转换为除某些引用之外的任何算术类型

Type cast operators to any arithmetic type except some reference

本文关键字:任何算 类型 引用 类型转换 运算符      更新时间:2023-10-16

假设我们有这样一个示例类:

class Union {
    union Value {
        int i;
        float f;
    };
    enum class Type {
        Int, Float
    };
    Type type;
    Value value;
public:
    operator int&() { return value.i; }
    operator float&() { return value.f; }
    template <typename T, is_arithmetic<T>>
    operator T() const {
        if (type == Type::Int)
            return static_cast<T>(value.i);
        else
            return static_cast<T>(value.f);
    }
}

我想允许Union实例被强制转换为任何算术类型,但禁止强制转换为引用,除了示例中的int和float类型。对于给定的示例,编译器通知存在多个转换。如何处理这样的问题?这可能吗?

问题是is_arithmetic<T>。它并不像你想象的那样。这是一个模板非类型参数。is_arithmetic是一个类,一个类型。

这样想:

template <class T, int N>
struct X {};

您也可以省略参数名称:

template <class T, int>
struct X {};

现在有了is_arithmetic<T>而不是int

去掉它,它就起作用了:

template <typename T>
operator T() const {

我的观点是,你不需要确保T是一个算术类型,就像static_cast为你做的那样。

如果你想在声明中强制执行,你需要SFINAE和enable_if,也就是说,直到我们有了概念:

template <class T, class Enable = std::enable_if_t<std::is_arithmetic<T>::value>>
operator T() const {

我对你的设计也有一些顾虑。根据经验,隐式类型转换是不好的。所以你至少可以把它们说清楚。

我提出了一个类似于实现给定运算符的解决方案:

operator int&();
operator float&();
operator T();
operator T() const;

有了这组运算符,我可以像预期的那样定义算术变量,即非常量、常量、常量引用和针对int和float等特定类型的额外引用。