ベクトルの要素へのアクセス 〜その3〜

#include <boost/iterator_adaptors.hpp>

#include <d3dx9.h>

struct my_vec{
    float x, y, z;
};

//-----------------------------------------------------------------------------

template<typename T>
struct vec_traits;

template<>
struct vec_traits<my_vec>{
    static const int dimension = 3;
    typedef float value_type;
    typedef my_vec vec_type;
    
    struct iterator
        : public boost::iterator_adaptor<
            iterator,
            value_type*,
            value_type&,
            boost::random_access_traversal_tag
        >{
        iterator(vec_traits::value_type* f) : iterator_adaptor_(f){}
    };

    static const value_type& get_x(const vec_type& v){
        return v.x;
    }
    static void set_x(vec_type& v, const value_type& value){
        v.x = value;
    }

    static iterator begin(vec_type& v){
        return iterator(&v.x);
    };
    static iterator end(vec_type& v){
        return iterator( &(v.z) + 1 );
    };
};

template<>
struct vec_traits<D3DVECTOR>{
    static const int dimension = 3;
    typedef float value_type;
    typedef D3DVECTOR vec_type;
    
    struct iterator
        : public boost::iterator_adaptor<
            iterator,
            value_type*,
            value_type&,
            boost::random_access_traversal_tag
        >{
        iterator(vec_traits::value_type* f) : iterator_adaptor_(f){}
    };

    static const value_type& get_x(const vec_type& v){
        return v.x;
    }
    static void set_x(vec_type& v, const value_type& value){
        v.x = value;
    }

    static iterator begin(vec_type& v){
        return iterator(&v.x);
    };
    static iterator end(vec_type& v){
        return iterator( &(v.z) + 1 );
    };
};

template<>
struct vec_traits<D3DXVECTOR3> : public vec_traits<D3DVECTOR>{};

//-----------------------------------------------------------------------------

template<typename T>
struct vec_value_type{
    typedef typename vec_traits<T>::value_type type;
};

template<typename T>
struct vec_dimension{
    static const int value = vec_traits<T>::dimension;
};

template<typename T>
struct vec_iterator{
    typedef typename vec_traits<T>::iterator type;
};

template<typename T>
struct vec_get_x{
    const typename vec_value_type<T>::type&
    operator ()(const T& v){
        return vec_traits<T>::get_x(v);
    }
};

template<typename T>
struct vec_set_x{
    void
    operator ()(T& v, const typename vec_value_type<T>::type& value){
        vec_traits<T>::set_x(v, value);
    }
};

//-----------------------------------------------------------------------------

template<typename T>
const typename vec_value_type<T>::type&
get_x(const T& v){
    return vec_get_x<T>()(v);
}

template<typename T>
void
set_x(T& v, const typename vec_value_type<T>::type& value){
    vec_set_x<T>()(v, value);
}

template<typename T>
typename vec_iterator<T>::type
begin(T& v){
    return vec_traits<T>::begin(v);
}

template<typename T>
typename vec_iterator<T>::type
end(T& v){
    return vec_traits<T>::end(v);
}

template<typename T>
struct vec_range{
    typedef T vec_type;
    typedef typename vec_iterator<T>::type iterator;

    iterator begin(){
        return ::begin(v);
    }
    iterator end(){
        return ::end(v);
    }

    vec_range(vec_type& rhs) : v(rhs){}
private:
    vec_type& v;
};

template<typename T>
vec_range<T>
make_vec_range(T& v){
    return vec_range<T>(v);
}

template<typename T>
typename vec_iterator<T>::type::value_type
at(T& v, std::size_t n){
    return vec_traits<T>::begin(v)[n];
}

//-----------------------------------------------------------------------------

int
main(){
    
    my_vec    vec;
    set_x(vec, 0.0f);
    assert(vec.x == get_x(vec) );
    
    at(vec, 0) = 0.0f;
    at(vec, 1) = 1.0f;
    at(vec, 2) = 2.0f;

    auto range = make_vec_range(vec);
    std::for_each(range.begin(), range.end(),
        [](float value){ std::cout << value << " "; });

    std::valarray<float>    val_vec(3);

    // DirectX
    D3DVECTOR    d3d_vec;
    set_x(d3d_vec, 0.0f);
    assert(d3d_vec.x == get_x(d3d_vec) );
    
    D3DXVECTOR3    d3dx_vec;
    set_x(d3dx_vec, 0.0f);
    assert(d3dx_vec.x == get_x(d3dx_vec) );
    
    return 0;
}


変に考えないで素直に書いてみました。
大元に、 vec_traits があり、各 traits → 各関数につなげて呼び出しを行います。
各 traits で template の特殊化をして実装を行ってもいいし、関数のオーバーロードを使用して実装してもいいので、割と拡張子がしやすいんじゃないかと。
あちこちで実装するのがめんどくさいのであれば、vec_traits にまとめてしまえばいいわけですし。
何はともあれ、最初にあれこれ頭の中で考えるよりも、先に大きい風呂敷を広げて、畳んだ方がいいですね。