template に float 値を渡す

こんな感じでどうか。

[ソース]

#include <boost/preprocessor/repetition/enum.hpp>
#include <sprout/string.hpp>
#include <sprout/cstdlib.hpp>
#include <sprout/operation.hpp>


template<std::size_t Index, typename String>
constexpr char
at_c(String const& str){
    return Index >= str.length()
         ? char('\0')
         : str[Index];
}

template<char... cs>
struct chars{};


#define STRING_MAX_LENGTH    16

#define DECL_AT_C(z, n, text)    \
    at_c<n>(sprout::to_string(text))

#define _(str)    \
    chars<BOOST_PP_ENUM(STRING_MAX_LENGTH, DECL_AT_C, str)>


template<typename T>
struct float_;

template<char... cs>
struct float_<chars<cs...>>{
    static constexpr sprout::string<16> string
        = sprout::realign_to<sprout::string<16>>(sprout::make_string(cs...));
    static constexpr float value = sprout::atof(string.c_str());
};

template<char... cs>
constexpr sprout::string<16> float_<chars<cs...>>::string;

template<char... cs>
constexpr float float_<chars<cs...>>::value;


template<typename T, typename U>
struct plus{
    static constexpr decltype(T::value + U::value) value = T::value + U::value;
};

template<typename T, typename U>
constexpr decltype(T::value + U::value) plus<T, U>::value;


int
main(){
    typedef float_<_(0.25f)> X;

    static_assert(X::value == 0.25f, "");
    static_assert(plus<X, float_<_(0.5f)>>::value == 0.75f, "");

    return 0;
}


float_<0.25f> の様に直接 float 値を渡すことはできません。
なので、一旦 float 値を文字列にして template に渡し、再度 float 値へと変換を行っています。
Sprout が使えないと出来ない芸当ですね。
これで比較的簡単に float 値を template に渡すことが出来るので色々と出来そう。
たのしい。

[コンパイラ]

  • g++ (GCC) 4.8.0 20120415 (experimental)