vec::extension::visit

重要なファクターその3
visitorパターンを利用して vec へ対して操作を行っていきます。
例によって operator| で簡易接続。
まぁここら辺は殆ど『C++テンプレートテクニック』を真似ているだけなんですが…。

#include 
#include 
#include 

#include "vec/vec.hpp"

#include "vec/extension/visit.hpp"
#include "vec/type_traits/value.hpp"

namespace kmt_ex{ namespace math{ namespace vec{ namespace extension{

/**
 ベクトル型を std::string に変換
 */
struct to_string_impl{
    
    typedef std::string result_type;
    
    template<
        int D,
        typename T
    >
    std::string operator ()(const vec& vec) const{
        std::ostringstream    oss;
        oss << "{ ";
        for( int i = 0 ; i < D ; i++ ){
            oss << vec.value[i] << " ";
        }
        oss << "}";
        return oss.str();
    }
};
static const to_string_impl to_string;

} } } }        // namespace kmt_ex{ namespace math{ namespace vec{ namespace extension{


namespace vec{ namespace sample{

namespace vec = kmt_ex::math::vec;
typedef vec::vec<3, float>    vec3;


void
visit_main(){
    
    using kmt_ex::math::vec::extension::to_string;
    
    vec3    v;
    v.value[0] = 0.5f;
    v.value[1] = 1.5f;
    v.value[2] = 2.5f;
    
    std::cout << vec::extension::visit(v, to_string) << "\n";
    std::cout << (v|to_string) << "\n";	// operator | での呼び出し
}

}; };
/**
    ベクトル型に対しての操作を行う
    
    以下の条件をFが満たしていれば使用可能
    1.関数か、関数オブジェクト(operator()が定義されているクラス)
    2.関数オブジェクトの場合は、戻り値を定義しておく必要がある
      result_type か、template struct result{ type };の定義
 */
template<
    typename T,
    typename F
>
typename detail::result_of::type
visit(T& obj, F func){
    return func(obj);
};

template<
    typename T,
    typename F
>
typename detail::result_of::type
visit(const T& obj, F func){
    return func(obj);
};

template<
    typename T,
    typename F
>
typename detail::result_of::type
operator |(T& obj, F func){
    return visit(obj, func);
};

template<
    typename T,
    typename F
>
typename detail::result_of::type
operator |(const T& obj, F func){
    return visit(obj, func);
};

自前で、result_of を実装してみたけどかなりやんちゃな事をしているので、
かなり胡散臭いです…。
あーboost 使いたいー。