User-defined literals で小数から型を定義

float<3,0014> とかどうするの?
などと露骨にツッコまれてしまったので、User-defined literals を使って定義し直し。
なぜ気づかないんだ>わたし。
これで問題ない…はず。

[ソース]

#include <type_traits>

namespace detail{

constexpr std::size_t
pow(std::size_t n, std::size_t m){
    return m == 0 ? 1
         : n * pow(n, m-1);
}

template<char C>
struct ctoi : std::integral_constant<int, C - '0'>{};

template<int acc, char ...cs>
struct atoi_impl
    : std::integral_constant<int, acc>{};

template<int acc, char c, char ...cs>
struct atoi_impl<acc, c, cs...>
    : atoi_impl<c == '.' ? acc : (acc * 10) + (c - '0'), cs...>{};

template<char ...cs>
struct num_impl : atoi_impl<0, cs...>{};


template<char ...cs>
struct den_impl;

template<char c, char ...cs>
struct den_impl<c, cs...> : std::conditional<
    c == '.',
    std::integral_constant<std::size_t, pow(10, sizeof...(cs))>,
    den_impl<cs...>
>::type{};


template<>
struct den_impl<> : std::integral_constant<std::size_t, 0>{};

}  // namespace detail

template<char... cs>
struct num : detail::num_impl<cs...>{};


template<char... cs>
struct den : detail::den_impl<cs...>{};


template<int Num, std::size_t Den>
struct ratio{
    static int const num = Num;
    static std::size_t const den = Den;
    constexpr ratio<-Num, Den>
    operator -() const{
        return ratio<-Num, Den>{};
    }
    constexpr operator float() const{
        return float(Num) / Den;
    }
};


template<char... cs>
constexpr ratio<num<cs...>::value, den<cs...>::value>
operator "" _f(){
    return ratio<num<cs...>::value, den<cs...>::value>{};
}


#include <boost/constrained_value.hpp>
#include <iostream>


int
main() try{
    static_assert(-10.25_f == -10.25, "");
    static_assert(decltype(-0.5_f)() == -0.5, "");

    using boost::constrained_value::bounded;
    bounded<float, decltype(-0.12_f), decltype(0.2_f)>::type value(-0.1f);

    for(int i = 0 ; i < 20 ; ++i){
        std::cout << value << std::endl;
        value = value + 0.03f;
    }
    
    return 0;
}
catch(boost::constrained_value::broken_constraint const& exp){
    std::cout << exp.what() << std::endl;
}

[出力]

-0.1
-0.07
-0.04
-0.01
0.02
0.05
0.08
0.11
0.14
0.17
0.2

User-defined literals は "-" を受け取らないんですね。
マイナスの場合は、operator -で処理しています。
んーなんで例外をキャッチしていないんだろう。

[boost]

  • ver 1.47.0

[コンパイラ]

  • g++ (GCC) 4.7.0 20111112 (experimental)