#include <iostream>
template< typename T >
struct v_traits;
template< typename T, int index>
struct access {};
struct float3 { float x, y, z; };
std::ostream & operator<<( std::ostream & os, const float3 & v ) {
os << "{" << v.x << ", " << v.y << ", " << v.z << "}";
return os;
}
template<>
struct v_traits<float3> {
typedef float3 vector_type;
typedef float element_type;
typedef element_type & element_ref;
};
template<>
struct access<float3,0> {
static float & get( float3 & v ) { return v.x; }
};
template<>
struct access<float3,1> {
static float & get( float3 & v ) { return v.y; }
};
template<>
struct access<float3,2> {
static float & get( float3 & v ) { return v.z; }
};
template< int index, typename T >
typename v_traits<T>::element_ref get( T & v ) {
return access<T,index>::get( v );
}
template< typename T0 >
struct vec1_view {
T0 & x;
vec1_view( T0 & x_ ) : x(x_) {}
vec1_view( vec1_view && v ) : x(v.x) {}
vec1_view & operator=( T0 x_ ) {
x = x_;
return *this;
}
template< typename U0 >
vec1_view & operator=( const vec1_view<U0> & v ) {
x = v.x;
return *this;
}
vec1_view & operator=( const vec1_view & v ) {
x = v.x;
return *this;
}
};
template< typename T0, typename T1 >
struct vec2_view {
T0 & x;
T1 & y;
vec2_view( T0 & x_, T1 & y_ ) : x(x_), y(y_) {}
vec2_view( vec2_view && v ) : x(v.x), y(v.y) {}
vec2_view & operator=( const vec2_view & v ) {
x = v.x;
y = v.y;
return *this;
}
template< typename U0, typename U1 >
vec2_view & operator=( const vec2_view<U0, U1> & v ) {
x = v.x;
y = v.y;
return *this;
}
};
namespace swizzle {
#define SWIZZLE_ENUM( mask ) enum swizzle_##mask { mask };
SWIZZLE_ENUM( x )
SWIZZLE_ENUM( y )
SWIZZLE_ENUM( z )
SWIZZLE_ENUM( xx )
SWIZZLE_ENUM( xy )
SWIZZLE_ENUM( xz )
SWIZZLE_ENUM( yx )
SWIZZLE_ENUM( yy )
SWIZZLE_ENUM( yz )
SWIZZLE_ENUM( zx )
SWIZZLE_ENUM( zy )
SWIZZLE_ENUM( zz )
}
#define SWIZZLE_OP1( mask, a ) \
template< typename V > \
vec1_view<typename v_traits<V>::element_type> \
operator,( V & v, swizzle::swizzle_##mask ) { \
typedef typename v_traits<V>::element_type element_type; \
typedef vec1_view<element_type> view_type; \
return view_type( get<a>( v ) ); \
} \
SWIZZLE_OP1( x, 0 )
SWIZZLE_OP1( y, 1 )
SWIZZLE_OP1( z, 2 )
#define SWIZZLE_OP2( mask, a, b ) \
template< typename V > \
vec2_view<typename v_traits<V>::element_type, typename v_traits<V>::element_type> \
operator,( V & v, swizzle::swizzle_##mask ) { \
typedef typename v_traits<V>::element_type element_type; \
typedef vec2_view<element_type, element_type> view_type; \
return view_type( get<a>( v ), get<b>( v ) ); \
} \
SWIZZLE_OP2( xx, 0, 0 )
SWIZZLE_OP2( xy, 0, 1 )
SWIZZLE_OP2( xz, 0, 2 )
SWIZZLE_OP2( yx, 1, 0 )
SWIZZLE_OP2( yy, 1, 1 )
SWIZZLE_OP2( yz, 1, 2 )
SWIZZLE_OP2( zx, 2, 0 )
SWIZZLE_OP2( zy, 2, 1 )
SWIZZLE_OP2( zz, 2, 2 )
int main() {
float3 v;
using namespace swizzle;
(v,x) = 1.0f;
(v,y) = 2.0f;
(v,z) = 3.0f;
std::cout << v << std::endl;
(v,yz) = (v,xx);
std::cout << v << std::endl;
return 0;
}
I2luY2x1ZGUgPGlvc3RyZWFtPgoKdGVtcGxhdGU8IHR5cGVuYW1lIFQgPgpzdHJ1Y3Qgdl90cmFpdHM7Cgp0ZW1wbGF0ZTwgdHlwZW5hbWUgVCwgaW50IGluZGV4PgpzdHJ1Y3QgYWNjZXNzIHt9OwoKc3RydWN0IGZsb2F0MyB7IGZsb2F0IHgsIHksIHo7IH07CgpzdGQ6Om9zdHJlYW0gJiBvcGVyYXRvcjw8KCBzdGQ6Om9zdHJlYW0gJiBvcywgY29uc3QgZmxvYXQzICYgdiApIHsKCW9zIDw8ICJ7IiA8PCB2LnggPDwgIiwgIiA8PCB2LnkgPDwgIiwgIiA8PCB2LnogPDwgIn0iOwoJcmV0dXJuIG9zOwp9Cgp0ZW1wbGF0ZTw+CnN0cnVjdCB2X3RyYWl0czxmbG9hdDM+IHsKCXR5cGVkZWYgZmxvYXQzIHZlY3Rvcl90eXBlOwoJdHlwZWRlZiBmbG9hdCBlbGVtZW50X3R5cGU7Cgl0eXBlZGVmIGVsZW1lbnRfdHlwZSAmIGVsZW1lbnRfcmVmOwp9OwoKdGVtcGxhdGU8PgpzdHJ1Y3QgYWNjZXNzPGZsb2F0MywwPiB7CglzdGF0aWMgZmxvYXQgJiBnZXQoIGZsb2F0MyAmIHYgKSB7IHJldHVybiB2Lng7IH0KfTsKCnRlbXBsYXRlPD4Kc3RydWN0IGFjY2VzczxmbG9hdDMsMT4gewoJc3RhdGljIGZsb2F0ICYgZ2V0KCBmbG9hdDMgJiB2ICkgeyByZXR1cm4gdi55OyB9Cn07Cgp0ZW1wbGF0ZTw+CnN0cnVjdCBhY2Nlc3M8ZmxvYXQzLDI+IHsKCXN0YXRpYyBmbG9hdCAmIGdldCggZmxvYXQzICYgdiApIHsgcmV0dXJuIHYuejsgfQp9OwoKdGVtcGxhdGU8IGludCBpbmRleCwgdHlwZW5hbWUgVCA+CnR5cGVuYW1lIHZfdHJhaXRzPFQ+OjplbGVtZW50X3JlZiBnZXQoIFQgJiB2ICkgewoJcmV0dXJuIGFjY2VzczxULGluZGV4Pjo6Z2V0KCB2ICk7Cn0KCnRlbXBsYXRlPCB0eXBlbmFtZSBUMCA+CnN0cnVjdCB2ZWMxX3ZpZXcgewoJVDAgJiB4OwoKICAgIHZlYzFfdmlldyggVDAgJiB4XyApIDogeCh4Xykge30KCXZlYzFfdmlldyggdmVjMV92aWV3ICYmIHYgKSA6IHgodi54KSB7fQogICAgCiAgICB2ZWMxX3ZpZXcgJiBvcGVyYXRvcj0oIFQwIHhfICkgewogICAgICAgIHggPSB4XzsKICAgICAgICByZXR1cm4gKnRoaXM7CiAgICB9CgogICAgdGVtcGxhdGU8IHR5cGVuYW1lIFUwID4KICAgIHZlYzFfdmlldyAmIG9wZXJhdG9yPSggY29uc3QgdmVjMV92aWV3PFUwPiAmIHYgKSB7CiAgICAgICAgeCA9IHYueDsKICAgICAgICByZXR1cm4gKnRoaXM7CiAgICB9CgoJdmVjMV92aWV3ICYgb3BlcmF0b3I9KCBjb25zdCB2ZWMxX3ZpZXcgJiB2ICkgIHsKCQl4ID0gdi54OwoJCXJldHVybiAqdGhpczsKCX0KfTsKCnRlbXBsYXRlPCB0eXBlbmFtZSBUMCwgdHlwZW5hbWUgVDEgPgpzdHJ1Y3QgdmVjMl92aWV3IHsKCVQwICYgeDsKCVQxICYgeTsKCiAgICB2ZWMyX3ZpZXcoIFQwICYgeF8sIFQxICYgeV8gKSA6IHgoeF8pLCB5KHlfKSB7fQoJdmVjMl92aWV3KCB2ZWMyX3ZpZXcgJiYgdiApIDogeCh2LngpLCB5KHYueSkge30KCgl2ZWMyX3ZpZXcgJiBvcGVyYXRvcj0oIGNvbnN0IHZlYzJfdmlldyAmIHYgKSAgewoJCXggPSB2Lng7CgkJeSA9IHYueTsKCQlyZXR1cm4gKnRoaXM7Cgl9CgoJdGVtcGxhdGU8IHR5cGVuYW1lIFUwLCB0eXBlbmFtZSBVMSA+Cgl2ZWMyX3ZpZXcgJiBvcGVyYXRvcj0oIGNvbnN0IHZlYzJfdmlldzxVMCwgVTE+ICYgdiApIHsKCQl4ID0gdi54OwoJCXkgPSB2Lnk7CgkJcmV0dXJuICp0aGlzOwoJfQp9OwoKbmFtZXNwYWNlIHN3aXp6bGUgewojZGVmaW5lIFNXSVpaTEVfRU5VTSggbWFzayApIGVudW0gc3dpenpsZV8jI21hc2sgeyBtYXNrIH07CiAgICBTV0laWkxFX0VOVU0oIHggKQogICAgU1dJWlpMRV9FTlVNKCB5ICkKICAgIFNXSVpaTEVfRU5VTSggeiApCiAgICBTV0laWkxFX0VOVU0oIHh4ICkKICAgIFNXSVpaTEVfRU5VTSggeHkgKQogICAgU1dJWlpMRV9FTlVNKCB4eiApCiAgICBTV0laWkxFX0VOVU0oIHl4ICkKICAgIFNXSVpaTEVfRU5VTSggeXkgKQogICAgU1dJWlpMRV9FTlVNKCB5eiApCiAgICBTV0laWkxFX0VOVU0oIHp4ICkKICAgIFNXSVpaTEVfRU5VTSggenkgKQogICAgU1dJWlpMRV9FTlVNKCB6eiApICAgIAp9CgojZGVmaW5lIFNXSVpaTEVfT1AxKCBtYXNrLCBhICkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCnRlbXBsYXRlPCB0eXBlbmFtZSBWID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKdmVjMV92aWV3PHR5cGVuYW1lIHZfdHJhaXRzPFY+OjplbGVtZW50X3R5cGU+ICAgICAgICAgICAgICAgICAgICAgXAogICAgb3BlcmF0b3IsKCBWICYgdiwgc3dpenpsZTo6c3dpenpsZV8jI21hc2sgKSB7ICAgICAgICAgICAgICAgICBcCiAgICB0eXBlZGVmIHR5cGVuYW1lIHZfdHJhaXRzPFY+OjplbGVtZW50X3R5cGUgZWxlbWVudF90eXBlOyAgICAgIFwKICAgIHR5cGVkZWYgdmVjMV92aWV3PGVsZW1lbnRfdHlwZT4gdmlld190eXBlOyAgICAgICAgICAgICAgICAgICAgXAogICAgcmV0dXJuIHZpZXdfdHlwZSggZ2V0PGE+KCB2ICkgKTsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCn0gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKClNXSVpaTEVfT1AxKCB4LCAwICkKU1dJWlpMRV9PUDEoIHksIDEgKQpTV0laWkxFX09QMSggeiwgMiApCgojZGVmaW5lIFNXSVpaTEVfT1AyKCBtYXNrLCBhLCBiICkgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCnRlbXBsYXRlPCB0eXBlbmFtZSBWID4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIFwKdmVjMl92aWV3PHR5cGVuYW1lIHZfdHJhaXRzPFY+OjplbGVtZW50X3R5cGUsIHR5cGVuYW1lIHZfdHJhaXRzPFY+OjplbGVtZW50X3R5cGU+ICAgXApvcGVyYXRvciwoIFYgJiB2LCBzd2l6emxlOjpzd2l6emxlXyMjbWFzayApIHsgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCiAgICB0eXBlZGVmIHR5cGVuYW1lIHZfdHJhaXRzPFY+OjplbGVtZW50X3R5cGUgZWxlbWVudF90eXBlOyAgICAgICAgICAgICAgICAgICAgICAgIFwKICAgIHR5cGVkZWYgdmVjMl92aWV3PGVsZW1lbnRfdHlwZSwgZWxlbWVudF90eXBlPiB2aWV3X3R5cGU7ICAgICAgICAgICAgICAgICAgICAgICAgXAogICAgcmV0dXJuIHZpZXdfdHlwZSggZ2V0PGE+KCB2ICksIGdldDxiPiggdiApICk7CQkJICAgICAgICAgICAgICAgICAgICAgICAgXAp9ICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBcCgpTV0laWkxFX09QMiggeHgsIDAsIDAgKQpTV0laWkxFX09QMiggeHksIDAsIDEgKQpTV0laWkxFX09QMiggeHosIDAsIDIgKQpTV0laWkxFX09QMiggeXgsIDEsIDAgKQpTV0laWkxFX09QMiggeXksIDEsIDEgKQpTV0laWkxFX09QMiggeXosIDEsIDIgKQpTV0laWkxFX09QMiggengsIDIsIDAgKQpTV0laWkxFX09QMiggenksIDIsIDEgKQpTV0laWkxFX09QMiggenosIDIsIDIgKQoKCmludCBtYWluKCkgewogICAgZmxvYXQzIHY7CiAgICB1c2luZyBuYW1lc3BhY2Ugc3dpenpsZTsKICAgICh2LHgpID0gMS4wZjsKICAgICh2LHkpID0gMi4wZjsKICAgICh2LHopID0gMy4wZjsKCglzdGQ6OmNvdXQgPDwgdiA8PCBzdGQ6OmVuZGw7CgogICAgKHYseXopID0gKHYseHgpOwoKCXN0ZDo6Y291dCA8PCB2IDw8IHN0ZDo6ZW5kbDsKICAgIHJldHVybiAwOwp9Cg==