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

时间:2016-03-29 16:31:58

标签: c++ casting operator-overloading

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

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类型之外。对于给定的示例,编译器会通知有关现有的多个转换。如何处理这样的问题?它甚至可能吗?

2 个答案:

答案 0 :(得分:1)

问题是is_arithmetic<T>。它不是你认为它做的。这是一个模板非类型参数。 is_arithmetic是一个类,一个类型。

这样想:

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

您还可以省略参数名称:

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

现在取代int而不是is_arithmetic<T>

摆脱它并且它有效:

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 {

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

答案 1 :(得分:0)

我想出了一个像实现给定运算符的解决方案:

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

使用这组运算符,我能够像我期望的那样定义算术变量,即非const,const,const引用和特定类型的额外引用,如int和float。