Boost.Ratio の定義を float っぽく記述する

float というか、実数ですね。
あくまでも、それっぽく記述するだけなので、中身は Boost.Ratio です。
まぁ書きやすくはなるんじゃないでしょうか。

[ソース]

#include <boost/mpl/assert.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/ratio/mpl/times.hpp>
#include <boost/ratio/mpl/equal_to.hpp>

namespace mpl = boost::mpl;

BOOST_MPL_ASSERT(( mpl::equal_to<float_<123,456>, boost::ratio<123456, 1000> > ));
BOOST_MPL_ASSERT(( mpl::equal_to<float_<3,14>, boost::ratio<314, 100> > ));

typedef mpl::vector<float_<0,1>, float_<0,2>, float_<0,3>, float_<0,4>, float_<0,5> > seq;

struct disp{
    template<typename T>
    void operator ()(T const& t) const{
        std::cout << boost::rational_cast<float>(t.value()) << ", ";
    }
};

int
main(){
    std::cout << boost::rational_cast<float>(float_<3,14>().value()) << std::endl;
    mpl::for_each<seq>(disp());
    std::cout << "\n";
    mpl::for_each<mpl::transform<seq, mpl::multiplies<mpl::_1, mpl::int_<2> > >::type>(disp());
    return 0;
}

[出力]

3.14
0.1, 0.2, 0.3, 0.4, 0.5, 
0.2, 0.4, 0.6, 0.8, 1, 

float_<3,14> の様に、"." の変わりに "," を使うような感じです。
まぁ中身はゴリ押しで実装しているので速度的にはちょっと怪しいところがありますが……。

[boost]

  • ver 1.47.0


全てのソースは以下から

#define BOOST_RATIO_EXTENSIONS
#include <boost/ratio/ratio.hpp>
#include <boost/mpl/int.hpp>
#include <boost/mpl/less_equal.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/divides.hpp>
#include <boost/mpl/multiplies.hpp>
#include <boost/mpl/minus.hpp>

namespace boost { namespace mpl{

template<typename base, typename exponent>
struct pow : 
    if_<
        less_equal<exponent, int_<0> >,
        int_<1>,
        multiplies<pow<base, minus<exponent, int_<1> > >, base>
    >::type
{};

template<std::size_t base, std::size_t exponent>
struct pow_c : pow<
    integral_c<std::size_t, base>,
    integral_c<std::size_t, exponent>
>{};

} } // namespace boost { namespace mpl{


namespace detail{

namespace mpl = boost::mpl;

template<typename T>
struct keta_impl :
    mpl::if_<
        mpl::less_equal<T, mpl::int_<0> >,
        mpl::int_<0>,
        mpl::plus<keta_impl<mpl::divides<T, mpl::int_<10> > >, mpl::int_<1> >
    >::type
{};

}  // namespace detai

template<typename T>
struct keta : detail::keta_impl<T>{};

namespace detail{

template<std::size_t N, std::size_t M,
    typename keta = mpl::pow<mpl::int_<10>, keta<mpl::integral_c<std::size_t, M> > > >
struct float_impl : 
    boost::ratio<
        N * keta::value + M,
        keta::value
    >
{};

}  // namespace detail

template<std::size_t N, std::size_t M>
struct float_ : detail::float_impl<N, M>{};


#include <boost/mpl/assert.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/transform.hpp>
#include <boost/ratio/mpl/times.hpp>
#include <boost/ratio/mpl/equal_to.hpp>

namespace mpl = boost::mpl;

BOOST_MPL_ASSERT(( mpl::equal_to<keta<mpl::int_<123> >, mpl::int_<3> > ));
BOOST_MPL_ASSERT(( mpl::equal_to<mpl::pow_c<10, 3>::type, mpl::int_<1000> > ));

BOOST_MPL_ASSERT(( mpl::equal_to<float_<123,456>, boost::ratio<123456, 1000> > ));
BOOST_MPL_ASSERT(( mpl::equal_to<float_<3,14>, boost::ratio<314, 100> > ));

typedef mpl::vector<float_<0,1>, float_<0,2>, float_<0,3>, float_<0,4>, float_<0,5> > seq;

struct disp{
    template<typename T>
    void operator ()(T const& t) const{
        std::cout << boost::rational_cast<float>(t.value()) << ", ";
    }
};

int
main(){
    std::cout << boost::rational_cast<float>(float_<3,14>().value()) << std::endl;
    mpl::for_each<seq>(disp());
    std::cout << "\n";
    mpl::for_each<mpl::transform<seq, mpl::multiplies<mpl::_1, mpl::int_<2> > >::type>(disp());
    return 0;
}