c++ - 在 C++ 中包装算术类型

标签 c++ templates operators

C++ 非常棒,但是您不能从算术类型继承,这有时会很有用。我写了以下内容:

template <typename type> class arithmetic
{
    static_assert(std :: is_arithmetic <type> :: value, "Please provide an arithmetic type.");

    // Members

    type _value;

public:

    // Constructors

    inline arithmetic() = default;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline arithmetic(const rtype &);

    // Arithmetic operators

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator + (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator - (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator * (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator / (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator % (const rtype &) const;

    inline auto operator + () const;
    inline auto operator - () const;

    inline auto operator ++ ();
    inline auto operator ++ (int);

    inline auto operator -- ();
    inline auto operator -- (int);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator = (const rtype &);

    // Comparison operators

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator == (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator != (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator > (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator < (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator >= (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator <= (const rtype &) const;

    // Logical operators

    inline auto operator ! () const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator && (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator || (const rtype &) const;

    // Bitwise operators

    inline auto operator ~ () const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator & (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator | (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator ^ (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator << (const rtype &) const;

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator >> (const rtype &) const;

    // Compound assignment operators

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator += (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator -= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator *= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator /= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator %= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator &= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator |= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator ^= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator <<= (const rtype &);

    template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type * = nullptr> inline auto operator >>= (const rtype &);

    // Member and pointer operators

    inline type * operator & ();
    inline const type * operator & () const;

    // Casting

    inline operator type & ();
    inline operator const type & () const;
};

// Constructors

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline arithmetic <type> :: arithmetic(const rtype & value) : _value(value)
{
}

// Arithmetic operators

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator + (const rtype & rvalue) const
{
    return this->_value + rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator - (const rtype & rvalue) const
{
    return this->_value - rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator * (const rtype & rvalue) const
{
    return this->_value * rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator / (const rtype & rvalue) const
{
    return this->_value / rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator % (const rtype & rvalue) const
{
    return this->_value % rvalue;
}

template <typename type> inline auto arithmetic <type> ::  operator + () const
{
    return +(this->_value);
}

template <typename type> inline auto arithmetic <type> ::  operator - () const
{
    return -(this->_value);
}

template <typename type> inline auto arithmetic <type> ::  operator ++ ()
{
    return ++(this->_value);
}

template <typename type> inline auto arithmetic <type> ::  operator ++ (int)
{
    return (this->_value)++;
}

template <typename type> inline auto arithmetic <type> ::  operator -- ()
{
    return --(this->_value);
}

template <typename type> inline auto arithmetic <type> ::  operator -- (int)
{
    return (this->_value)++;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator = (const rtype & rvalue)
{
    return this->_value = rvalue;
}

// Comparison operators

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator == (const rtype & rvalue) const
{
    return this->_value == rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator != (const rtype & rvalue) const
{
    return this->_value != rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator > (const rtype & rvalue) const
{
    return this->_value > rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator < (const rtype & rvalue) const
{
    return this->_value < rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator >= (const rtype & rvalue) const
{
    return this->_value >= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator <= (const rtype & rvalue) const
{
    return this->_value <= rvalue;
}

// Logical operators

template <typename type> inline auto arithmetic <type> ::  operator ! () const
{
    return !(this->_value);
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator && (const rtype & rvalue) const
{
    return this->_value && rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator || (const rtype & rvalue) const
{
    return this->_value || rvalue;
}

// Bitwise operators

template <typename type> inline auto arithmetic <type> ::  operator ~ () const
{
    return ~(this->_value);
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator & (const rtype & rvalue) const
{
    return this->_value & rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator | (const rtype & rvalue) const
{
    return this->_value | rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator ^ (const rtype & rvalue) const
{
    return this->_value ^ rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator << (const rtype & rvalue) const
{
    return this->_value << rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator >> (const rtype & rvalue) const
{
    return this->_value >> rvalue;
}

// Compound assignment operators

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator += (const rtype & rvalue)
{
    return this->_value += rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator -= (const rtype & rvalue)
{
    return this->_value -= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator *= (const rtype & rvalue)
{
    return this->_value *= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator /= (const rtype & rvalue)
{
    return this->_value /= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator %= (const rtype & rvalue)
{
    return this->_value %= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator &= (const rtype & rvalue)
{
    return this->_value &= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator |= (const rtype & rvalue)
{
    return this->_value |= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator ^= (const rtype & rvalue)
{
    return this->_value ^= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator <<= (const rtype & rvalue)
{
    return this->_value <<= rvalue;
}

template <typename type> template <typename rtype, typename std :: enable_if <__arithmetic :: __is_arithmetic_convertible <rtype> :: value> :: type *> inline auto arithmetic <type> ::  operator >>= (const rtype & rvalue)
{
    return this->_value >>= rvalue;
}

// Member and pointer operators

template <typename type> inline type * arithmetic <type> :: operator & ()
{
    return &(this->_value);
}

template <typename type> inline const type * arithmetic <type> :: operator & () const
{
    return &(this->_value);
}

// Casting

template <typename type> inline arithmetic <type> :: operator type & ()
{
    return this->_value;
}

template <typename type> inline arithmetic <type> :: operator const type & () const
{
    return this->_value;
}

这基本上只是算术类型的一个非常迂腐的包装。包装器有一个名为 _value 的算术成员。 ,那么对任何运算符(operator)的所有调用都会转发到 _value ,并且有一个转换运算符到原始算术类型。

现在,我想知道是否有任何情况,比如说 arithmetic <int>的行为与 int 不同?我似乎无法弄清楚,但我想我应该询问更明智的意见。

另一方面,如果这按预期工作并且 arithmetic <int>表现为 int ,那么为什么这部分不是标准呢?它看起来实现起来非常简单,并且允许我们随意扩展算术类型。

最佳答案

一个最重要的问题 - 隐式转换序列中不超过一个用户定义的转换。考虑:

class C { C(int); };
void f(C);

f(42);  // works, calls f(C(42));
f(arithmetic<int>(42));  // wouldn't work.

另一个问题 - 模板特化:

template <typename T> void f(T) { std::cout << "Generic"; }
template <> void f<int>(int) { std::cout << "Specialized"; }

f(42);  // calls specialized
f(arithmetic<int>(42));  // calls generic

言归正传——你可以使用arithmetic<int>但不是arithmetic<arithmetic<int>> 。更一般地说,各种模板元编程技术能够区分差异。

关于c++ - 在 C++ 中包装算术类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38101333/

相关文章:

c++ - 类C,构造函数和统一初始化之间有什么区别?

c++ - 从C++中动态分配的数组中删除对象

c++ - 使用 typeid 分离代码执行

javascript - JavaScript 中的逻辑运算符及其行为

c++ - SDL2 - 找不到 lsdlmain 和 lsdl。代码块

c++ - 如何在没有参数包的情况下扩展模式?

javascript - 如何在 mustache 模板化后检查元素是否存在

c++ - 我可以使用模板在 QString 和 std::string 之间进行自动转换吗?

c# - 在 C# 中使用 |= 运算符时发生了什么?

java - 自动捕获 Java 中 =+ 而不是 += 的使用