##// END OF EJS Templates
Removed forgotten files form previous impl of VC, fixed wrong submodules...
Removed forgotten files form previous impl of VC, fixed wrong submodules init (was always erasing changes :( ) Signed-off-by: Alexis Jeandet <alexis.jeandet@member.fsf.org>

File last commit:

r4:96a6baa9f92b
r31:dec007be0b03
Show More
numeric_typedef.hpp
260 lines | 10.0 KiB | text/x-c++hdr | CppLexer
#ifndef OPAQUE_NUMERIC_TYPEDEF_HPP
#define OPAQUE_NUMERIC_TYPEDEF_HPP
//
// Copyright (c) 2015, 2016
// Kyle Markley. All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// 1. Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
// 2. Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
// 3. Neither the name of the author nor the names of any contributors may be
// used to endorse or promote products derived from this software without
// specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
#include "binop/binop_inherit.hpp"
#include "data.hpp"
#include <type_traits>
#include <utility>
namespace opaque {
/// \addtogroup typedefs
/// @{
///
/// Numeric opaque typedef base type
///
/// Same as numeric_typedef, but without providing operator@ in terms of
/// operator@= by default. (Deriving from this rather than numeric_typedef
/// can avoid the need to remove a provided operator@ via a template
/// specialization.)
///
/// This is a suitable base class when you want to control the interface of
/// your type, including its interoperability with itself and other types.
/// Delete operations that you do not want, and add operations that you do
/// want.
///
/// You may define the behavior of mixed-type operator@ in your subclass by
/// inheriting from the opaque::binop::opname classes and providing the type
/// details. The list of template arguments for these classes is:
/// -# return type
/// -# commutative (bool)
/// -# type of left operand
/// -# type of right operand
/// -# type to convert left operand to
/// -# type to convert right operand to
///
/// If you do not desire certain standard numeric operations, simply delete
/// them in your subclass. (Note that it is simpler to delete an unwanted
/// operation than to supply a missing one that is desired.)
///
template <typename U, typename O, typename S = unsigned>
struct numeric_typedef_base : data<U,O> {
private:
using base = opaque::data<U,O>;
public:
using typename base::underlying_type;
using typename base::opaque_type;
typedef S shift_type;
using base::value;
constexpr14 opaque_type& operator*=(const opaque_type& peer) &
noexcept(noexcept( value *= peer.value )) {
value *= peer.value;
return downcast(); }
constexpr14 opaque_type& operator/=(const opaque_type& peer) &
noexcept(noexcept( value /= peer.value )) {
value /= peer.value;
return downcast(); }
constexpr14 opaque_type& operator%=(const opaque_type& peer) &
noexcept(noexcept( value %= peer.value )) {
value %= peer.value;
return downcast(); }
constexpr14 opaque_type& operator+=(const opaque_type& peer) &
noexcept(noexcept( value += peer.value )) {
value += peer.value;
return downcast(); }
constexpr14 opaque_type& operator-=(const opaque_type& peer) &
noexcept(noexcept( value -= peer.value )) {
value -= peer.value;
return downcast(); }
constexpr14 opaque_type& operator<<=(const shift_type& count) &
noexcept(noexcept( value <<= count )) {
value <<= count;
return downcast(); }
constexpr14 opaque_type& operator>>=(const shift_type& count) &
noexcept(noexcept( value >>= count )) {
value >>= count;
return downcast(); }
constexpr14 opaque_type& operator&=(const opaque_type& peer) &
noexcept(noexcept( value &= peer.value )) {
value &= peer.value;
return downcast(); }
constexpr14 opaque_type& operator^=(const opaque_type& peer) &
noexcept(noexcept( value ^= peer.value )) {
value ^= peer.value;
return downcast(); }
constexpr14 opaque_type& operator|=(const opaque_type& peer) &
noexcept(noexcept( value |= peer.value )) {
value |= peer.value;
return downcast(); }
constexpr14 opaque_type& operator++() &
noexcept(noexcept( ++value )) {
++value;
return downcast(); }
constexpr14 opaque_type& operator--() &
noexcept(noexcept( --value )) {
--value;
return downcast(); }
constexpr14 opaque_type operator++(int) & noexcept(noexcept(
std::declval<numeric_typedef_base&>().operator++()) and
std::is_nothrow_constructible<opaque_type, underlying_type>::value) {
opaque_type r(value); operator++(); return r; }
constexpr14 opaque_type operator--(int) & noexcept(noexcept(
std::declval<numeric_typedef_base&>().operator++()) and
std::is_nothrow_constructible<opaque_type, underlying_type>::value) {
opaque_type r(value); operator--(); return r; }
constexpr opaque_type operator+() const &
noexcept(noexcept( opaque_type(+ value ) )) {
return opaque_type(+ value ); }
constexpr14 opaque_type operator+() &&
noexcept(noexcept( opaque_type(+opaque::move(value)) )) {
return opaque_type(+opaque::move(value)); }
constexpr opaque_type operator-() const &
noexcept(noexcept( opaque_type(- value ) )) {
return opaque_type(- value ); }
constexpr14 opaque_type operator-() &&
noexcept(noexcept( opaque_type(-opaque::move(value)) )) {
return opaque_type(-opaque::move(value)); }
constexpr opaque_type operator~() const &
noexcept(noexcept( opaque_type(~ value ) )) {
return opaque_type(~ value ); }
constexpr14 opaque_type operator~() &&
noexcept(noexcept( opaque_type(~opaque::move(value)) )) {
return opaque_type(~opaque::move(value)); }
constexpr bool operator!() const
noexcept(noexcept( !value )) {
return !value; }
constexpr bool operator==(const opaque_type& peer) const
noexcept(noexcept( value == peer.value )) {
return value == peer.value; }
constexpr bool operator!=(const opaque_type& peer) const
noexcept(noexcept( value != peer.value )) {
return value != peer.value; }
constexpr bool operator< (const opaque_type& peer) const
noexcept(noexcept( value < peer.value )) {
return value < peer.value; }
constexpr bool operator> (const opaque_type& peer) const
noexcept(noexcept( value > peer.value )) {
return value > peer.value; }
constexpr bool operator<=(const opaque_type& peer) const
noexcept(noexcept( value <= peer.value )) {
return value <= peer.value; }
constexpr bool operator>=(const opaque_type& peer) const
noexcept(noexcept( value >= peer.value )) {
return value >= peer.value; }
/// Check whether the underlying value is nonzero
explicit constexpr operator bool() const
noexcept(noexcept( static_cast<bool>(value) )) {
return static_cast<bool>(value); }
using base::base;
explicit numeric_typedef_base() = default;
numeric_typedef_base(const numeric_typedef_base& ) = default;
numeric_typedef_base( numeric_typedef_base&&) = default;
numeric_typedef_base& operator=(const numeric_typedef_base& ) & = default;
numeric_typedef_base& operator=( numeric_typedef_base&&) & = default;
protected:
~numeric_typedef_base() = default;
using base::downcast;
};
///
/// Numeric opaque typedef
///
/// This is a base class providing wrappers for numeric operations on a
/// user-supplied type, which may be user-defined or built-in. The purpose of
/// this type is to easily enable the creation of several rigorously separate
/// numeric types so that they cannot be accidentally mixed in expressions,
/// implicitly converted, and also to enable overloading.
///
/// For example, you could create separate types for coordinates in each of
/// several dimensions, and it would be a compile-time error to mix those types
/// in a single expression, even if the the same underlying type was used to
/// represent all of them.
///
/// Template arguments for numeric_typedef:
/// -# U : The underlying type holding the value
/// -# O : The opaque type, your subclass
/// -# S : The right-hand operand type for shift operations
///
template <typename U, typename O, typename S = unsigned>
struct numeric_typedef : numeric_typedef_base<U,O,S>
, binop::multipliable <O>
, binop::dividable <O>
, binop::modulable <O>
, binop::addable <O>
, binop::subtractable <O>
, binop::left_shiftable <O, false, O, S>
, binop::right_shiftable<O, false, O, S>
, binop::bitandable <O>
, binop::bitxorable <O>
, binop::bitorable <O>
{
using numeric_typedef_base<U,O,S>::numeric_typedef_base;
explicit numeric_typedef() = default;
numeric_typedef(const numeric_typedef& ) = default;
numeric_typedef( numeric_typedef&&) = default;
numeric_typedef& operator=(const numeric_typedef& ) & = default;
numeric_typedef& operator=( numeric_typedef&&) & = default;
protected:
~numeric_typedef() = default;
};
/// @}
}
#endif