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
的算术成员,然后对任何运算符的所有调用都被转发到_value
,并且有一个对原始算术类型的强制转换运算符。
现在,我想知道,是否有任何情况,例如arithmetic <int>
的行为与int
不同?我似乎无法弄明白,但我想我会问更明智的意见。
另一方面,如果这按预期工作并且arithmetic <int>
表现为int
,那么为什么这部分不是标准?它实现起来非常简单,并且允许我们按照自己的意愿扩展算术类型。
答案 0 :(得分:2)
顶部的一个问题 - 在隐式转换序列中不超过一个用户定义的转换。考虑:
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>>
。更一般地说,各种模板元编程技术将能够分辨出差异。
答案 1 :(得分:0)
明确需要int类型的任何地方但是提供了arithmetic<int>
包装器,您应该担心。在某些情况下,定义隐式转换会有所帮助,但在涉及以下任何情况时无效:
int引用。 f(int&)
无法收到arithmetic<int>&
。此外,在这里,将对象转换为in将导致临时变量被修改,而不是原始对象。 f(int const&)
的函数可以合理地预期表现良好,因为你应该期望函数不能保持引用(但不能保证)。一般来说,如果您的整数和对象被视为不可变变量,您还可以从隐式转换中获得更多里程。
int指针。出于同样的原因。 int*
不是arithmetic<int>*
arithmetic<int>[]
。vector<arithmetic<int>>
,则无法使用vector<int>
。F<arithmetic<int>>
专门针对F<T>
,则无法提供F<int>
,但对于通用案例和,则无法提供您自己的专业化(嗯...这可能吗?例如,通过在.cxx中私下定义所有已知的特化)。 另外,实例化F声明的F。如果您的类确实是算术类型,那么您还必须能够声明arithmetic<int>
。在您的示例中:
static_assert(std :: is_arithmetic <type> :: value, "Please provide an arithmetic type.");
会导致失败。 (除非你专门针对所有T使用is_arithmetic&gt;。)