fork download
  1. #include <iostream>
  2.  
  3. template< typename T >
  4. struct v_traits;
  5.  
  6. template< typename T, int index>
  7. struct access {};
  8.  
  9. struct float3 { float x, y, z; };
  10.  
  11. std::ostream & operator<<( std::ostream & os, const float3 & v ) {
  12. os << "{" << v.x << ", " << v.y << ", " << v.z << "}";
  13. return os;
  14. }
  15.  
  16. template<>
  17. struct v_traits<float3> {
  18. typedef float3 vector_type;
  19. typedef float element_type;
  20. typedef element_type & element_ref;
  21. };
  22.  
  23. template<>
  24. struct access<float3,0> {
  25. static float & get( float3 & v ) { return v.x; }
  26. };
  27.  
  28. template<>
  29. struct access<float3,1> {
  30. static float & get( float3 & v ) { return v.y; }
  31. };
  32.  
  33. template<>
  34. struct access<float3,2> {
  35. static float & get( float3 & v ) { return v.z; }
  36. };
  37.  
  38. template< int index, typename T >
  39. typename v_traits<T>::element_ref get( T & v ) {
  40. return access<T,index>::get( v );
  41. }
  42.  
  43. template< typename T0 >
  44. struct vec1_view {
  45. T0 & x;
  46.  
  47. vec1_view( T0 & x_ ) : x(x_) {}
  48. vec1_view( vec1_view && v ) : x(v.x) {}
  49.  
  50. vec1_view & operator=( T0 x_ ) {
  51. x = x_;
  52. return *this;
  53. }
  54.  
  55. template< typename U0 >
  56. vec1_view & operator=( const vec1_view<U0> & v ) {
  57. x = v.x;
  58. return *this;
  59. }
  60.  
  61. vec1_view & operator=( const vec1_view & v ) {
  62. x = v.x;
  63. return *this;
  64. }
  65. };
  66.  
  67. template< typename T0, typename T1 >
  68. struct vec2_view {
  69. T0 & x;
  70. T1 & y;
  71.  
  72. vec2_view( T0 & x_, T1 & y_ ) : x(x_), y(y_) {}
  73. vec2_view( vec2_view && v ) : x(v.x), y(v.y) {}
  74.  
  75. vec2_view & operator=( const vec2_view & v ) {
  76. x = v.x;
  77. y = v.y;
  78. return *this;
  79. }
  80.  
  81. template< typename U0, typename U1 >
  82. vec2_view & operator=( const vec2_view<U0, U1> & v ) {
  83. x = v.x;
  84. y = v.y;
  85. return *this;
  86. }
  87. };
  88.  
  89. namespace swizzle {
  90. #define SWIZZLE_ENUM( mask ) enum swizzle_##mask { mask };
  91. SWIZZLE_ENUM( x )
  92. SWIZZLE_ENUM( y )
  93. SWIZZLE_ENUM( z )
  94. SWIZZLE_ENUM( xx )
  95. SWIZZLE_ENUM( xy )
  96. SWIZZLE_ENUM( xz )
  97. SWIZZLE_ENUM( yx )
  98. SWIZZLE_ENUM( yy )
  99. SWIZZLE_ENUM( yz )
  100. SWIZZLE_ENUM( zx )
  101. SWIZZLE_ENUM( zy )
  102. SWIZZLE_ENUM( zz )
  103. }
  104.  
  105. #define SWIZZLE_OP1( mask, a ) \
  106. template< typename V > \
  107. vec1_view<typename v_traits<V>::element_type> \
  108.   operator,( V & v, swizzle::swizzle_##mask ) { \
  109.   typedef typename v_traits<V>::element_type element_type; \
  110.   typedef vec1_view<element_type> view_type; \
  111.   return view_type( get<a>( v ) ); \
  112. } \
  113.  
  114. SWIZZLE_OP1( x, 0 )
  115. SWIZZLE_OP1( y, 1 )
  116. SWIZZLE_OP1( z, 2 )
  117.  
  118. #define SWIZZLE_OP2( mask, a, b ) \
  119. template< typename V > \
  120. vec2_view<typename v_traits<V>::element_type, typename v_traits<V>::element_type> \
  121. operator,( V & v, swizzle::swizzle_##mask ) { \
  122.   typedef typename v_traits<V>::element_type element_type; \
  123.   typedef vec2_view<element_type, element_type> view_type; \
  124.   return view_type( get<a>( v ), get<b>( v ) ); \
  125. } \
  126.  
  127. SWIZZLE_OP2( xx, 0, 0 )
  128. SWIZZLE_OP2( xy, 0, 1 )
  129. SWIZZLE_OP2( xz, 0, 2 )
  130. SWIZZLE_OP2( yx, 1, 0 )
  131. SWIZZLE_OP2( yy, 1, 1 )
  132. SWIZZLE_OP2( yz, 1, 2 )
  133. SWIZZLE_OP2( zx, 2, 0 )
  134. SWIZZLE_OP2( zy, 2, 1 )
  135. SWIZZLE_OP2( zz, 2, 2 )
  136.  
  137.  
  138. int main() {
  139. float3 v;
  140. using namespace swizzle;
  141. (v,x) = 1.0f;
  142. (v,y) = 2.0f;
  143. (v,z) = 3.0f;
  144.  
  145. std::cout << v << std::endl;
  146.  
  147. (v,yz) = (v,xx);
  148.  
  149. std::cout << v << std::endl;
  150. return 0;
  151. }
  152.  
Success #stdin #stdout 0s 3096KB
stdin
Standard input is empty
stdout
{1, 2, 3}
{1, 1, 1}