2017-01-17 3 views
0

Я хочу написать общий (математический) векторный класс, который поддерживает swizzling, для этого я нашел две ссылки (CxxSwizzle и Performance Optimal Vector Swizzling in C++ ²). Мне нравится прямолинейный стиль реализации swizzling в качестве подкласса членов профсоюза в ², но я хочу узнать о вариантах вариационного шаблона, как это делается в CxxSwizzle.Реализация векторного вектора C++ Variadic

Вот небольшой отрывок, который я не знаю, как реализовать (шаблонный функция SQRT находится здесь, чтобы реализовать длину/величину для определенного пользователя типов):

#include <cmath> 
#include <cstdint> 
#include <type_traits> 

template<class T> 
using vec_sqrt_function = typename std::add_pointer<T(const T)>::type; 

template<class VEC_TYPE, class T, vec_sqrt_function<T> SQRT_FN, std::int32_t... X> 
struct vec_impl 
{ 
    template<class VEC_TYPE2, class T2, vec_sqrt_function<T2> SQRT_FN2, std::int32_t... X2> 
    VEC_TYPE& operator +=(const vec<VEC_TYPE2, T2, SQRT_FN2, ...X2>& RHS) 
    { 
     // ??? 
     return *this; 
    } 
}; 

struct vec2 : public vec_impl<vec2, float, std::sqrt, 0, 1> 
{ 
    union 
    { 
     float data[2]; 

     vec_impl<vec2, float, std::sqrt, 0> x; 
     vec_impl<vec2, float, std::sqrt, 1> y; 

     vec_impl<vec2, float, std::sqrt, 0, 0> xx; 
     vec_impl<vec2, float, std::sqrt, 0, 1> xy; 
     vec_impl<vec2, float, std::sqrt, 1, 0> yx; 
     vec_impl<vec2, float, std::sqrt, 1, 1> yy; 
    }; 
}; 

Из того, что я понял из чтение нескольких учебных пособий заключается в том, что мне нужно специализировать vec_impl с шаблоном формы template<..., std::int32_t X, std::int32_t... REST>, но так как я использую тот же вариационный шаблон для оператора +=, мне нужно специализировать оператор += таким же образом, в целом для реализации того же функция 4 раза?

Есть ли более простой способ реализовать это (я не совсем понял, как CxxSwizzle реализует арифметику через все шаблоны)?

Редактировать: Для дальнейшего уточнения, что я хочу знать, как синтаксический реализовать следующий через переменные число шаблонов вместо раздельных классов:

template<class VEC_TYPE, class T, std::int32_t X1> 
struct vec1_swizzle 
{ 
    template<class VEC_TYPE2, class T2, std::int32_t Y1> 
    VEC_TYPE& operator += (const vec1_swizzle<VEC_TYPE2, T2, Y1>& RHS) 
    { 
     ((T*)this)[X1] += ((T*)&RHS)[Y1]; 
     return *this; 
    } 
} 

struct vec1f : public vec1_swizzle<vec1f, float, 0> 
{ 
    union 
    { 
     float data[1]; 
     vec1_swizzle<vec1f, float, 0> x; 
     vec2_swizzle<vec2f, float, 0, 0> xx; 
     // same for 3 & 4 
    } 
} 


template<class VEC_TYPE, class T, std::int32_t X1, std::int32_t X2> 
struct vec2_swizzle 
{ 
    template<class VEC_TYPE2, class T2, std::int32_t Y1, std::int32_t Y2> 
    VEC_TYPE& operator += (const vec1_swizzle<VEC_TYPE2, T2, Y1, Y2>& RHS) 
    { 
     ((T*)this)[X1] += ((T*)&RHS)[Y1]; 
     ((T*)this)[X2] += ((T*)&RHS)[Y2]; 
     return *this; 
    } 
} 

struct vec2f : public vec2_swizzle<vec2f, float, 0, 1> 
{ 
    union 
    { 
     float data[2]; 
     vec1_swizzle<vec1f, float, 0> x; 
     vec1_swizzle<vec1f, float, 1> y; 
     vec2_swizzle<vec2f, float, 0, 0> xx; 
     vec2_swizzle<vec2f, float, 0, 1> xy; 
     vec2_swizzle<vec2f, float, 1, 0> yx; 
     vec2_swizzle<vec2f, float, 1, 1> yy; 
     // same for 3 & 4 
    } 
} 

Я хочу «generify» в vec#_swizzle классе по шаблонам количество прошедших индексов.

+0

Добавление двух векторов имеет смысл только если они одинаковой длины, нет? – AndyG

+0

Это очень странный способ попытаться реализовать 'vec2'. Вы уверены, что понимаете, как работает профсоюз? Жесткая правда заключается в том, что многие из этого, похоже, слишком сложны для вашего уровня понимания языка на данном этапе. Начните с малого, с чтением о полиморфизме, а затем в векторах, а затем в стиле C++ 03. А затем вариативные шаблоны, статические утверждения, специализированные шаблоны, специализация частичного шаблона (особенно для функций-членов). И что такое союз. (boost :: variant или std :: variant также хорошо читаются). – AndyG

+0

@ AndyG Я думаю, что вы неправильно поняли мой вопрос. Я знаю, как реализовать то, что я хочу, используя отдельные шаблонные классы. Я спрашивал, как реализовать его в одном классе, если это имеет смысл (это скорее вопрос синтаксиса, чем логический вопрос), я редактировал вопрос, надеюсь, быть более ясно о том, что я хочу знать. – prydain

ответ

2

Не уверен, что вы хотите с накидной части, но после может помочь вам:

template<class VEC_TYPE, class T1, std::int32_t ... X1s> 
struct vec_swizzle 
{ 
    template<class VEC_TYPE2, class T2, std::int32_t ... Y1s> 
    VEC_TYPE& operator += (const vec1_swizzle<VEC_TYPE2, T2, Y1s...>& RHS) 
    { 
     static_assert(sizeof...(X1s) == sizeof...(Y1s), 
         "type mismatches"); // Better error message 

     // The "Loop" 
     const int dummy[] = { 0, ((((T1*)this)[X1s] += ((T2*)&RHS)[Y1s]), 0)...}; 
     static_cast<void>(dummy); // Avoid warning for unused variable 
     return *this; 
    } 
}; 

Или в C++ 17, с раскладным выражением:

template<class VEC_TYPE, class T1, std::int32_t ... X1s> 
struct vec_swizzle 
{ 
    template<class VEC_TYPE2, class T2, std::int32_t ... Y1s> 
    VEC_TYPE& operator += (const vec1_swizzle<VEC_TYPE2, T2, Y1s...>& RHS) 
    { 
     static_assert(sizeof...(X1s) == sizeof...(Y1s), 
         "type mismatches"); // Better error message 

     // The "Loop" 
     ((((T1*)this)[X1s] += ((T2*)&RHS)[Y1s]), ...); 
     return *this; 
    } 
}; 
+0

Работает отлично! Является ли это «идиоматическим» способом распаковать вариативные шаблоны, он чувствует себя немного хакерским (не так, чтобы использовать союзы для разных моделей памяти не было)? – prydain

+0

@prydain, C++ 17-кратные выражения упростили бы эти две строки до '((((T1 *) this) [X1s] + = ((T2 *) & RHS) [Y1s]), ...);' для теперь, хотя вы можете определить утилиту многократного использования: 'struct slurp {template Явный slurp (Args && ...) {}}; 'и использовать его:' slurp {(((T1 *) this) [X1s] + = ((T2 *) & RHS) [Y1s]) ...}; '. –

Смежные вопросы