Boost.Fusion の invoke を利用してみる

そういえば、こんな使い方が出来るのよね。
関数テンプレートを直接渡せないのが悲しいけど面白い。

[ソース]

#include <sprout/math/sqrt.hpp>

template<typename T>
constexpr T
length(T x, T y, T z){
    return sprout::sqrt(x * x + y * y + z * z);
}


#define BOOST_RESULT_OF_USE_DECLTYPE
#include <boost/fusion/include/invoke.hpp>

namespace detail{

struct length_obj{
    template<typename ...Args>
    constexpr auto
    operator ()(Args... args) const
    ->decltype(length(args...)){
        return length(args...);
    }
};

}  // namespace detail

template<typename T>
auto
length(T const& vec)
->decltype(boost::fusion::invoke(detail::length_obj{}, vec)){
    return boost::fusion::invoke(detail::length_obj{}, vec);
}


#include <boost/fusion/include/struct.hpp>

struct vec{
    float x;
    float y;
    float z;
};

BOOST_FUSION_ADAPT_STRUCT(vec, (float, x)(float, y)(float, z))


#include <cassert>

int
main(){
    auto len = length(1.0f, 2.0f, 3.0f);
    
    vec v = {1.0f, 2.0f, 3.0f};
    
    assert(length(v) == len);

    return 0;
}

[コンパイラ]

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