No double-to-int

// Copyright 2015 Andrzej Krzemienski.
//
// This shows how to use an auxiliary type to prevent implicit
// conversions from double to int

#include <type_traits>
#include <iostream>

# define ENABLE_IF(...)                                   \
  typename std::enable_if<__VA_ARGS__::value, bool>::type \
  = false                                                 \

template <typename T>
using is_signed_integral = typename std::conditional<
  std::is_signed<T>::value && std::is_integral<T>::value,
  std::true_type,
  std::false_type
>::type;

class only_int
{
  long long val_;
    
public:
  only_int (int v = 0) : val_(v) {}
  
  template <typename I, ENABLE_IF(is_signed_integral<I>)>  
    only_int (I v) : val_(v)
    {
      static_assert(sizeof(I) <= sizeof(int),
                   "too big int");
    } 
  
  template <typename T, ENABLE_IF(!is_signed_integral<T>)>
    only_int (T) = delete;

  int get() const { return val_; }
};

constexpr int pow(int base, int exp)
{
  return exp == 0 ? 1 : base * pow(base, exp - 1);
}

template <int Dec>
class FixedDecimal
{
  long long v_ = 0;

public:
  FixedDecimal (only_int i)
    : v_ (i.get() * pow(10, Dec)) {}
  FixedDecimal& operator *= (only_int s)
    { v_ *= s.get(); return *this; }
  FixedDecimal& operator /= (only_int s)
    { v_ /= s.get(); return *this; }
};

int main()
{
  FixedDecimal<2> d(5);
  // FixedDecimal<2> d(5.0); // will not compile
  d *= 5;
  // d *= 5.0;               // will not compile
}
Advertisements