Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[18.219.63.90] |
|
Сообщ.
#1
,
|
|
|
Всем привет.
Не получается сделать специализацию для контейнеров. Для массива работает, для std::array/std::vector не хочет. Вот есть такой код, никак понять не могу - как его специализировать для контейнеров? template<typename T, typename R> struct Euclidean { static inline R Distance(T q, T p) { auto diff = q - p; return static_cast<R>(std::sqrt( diff*diff )); } }; //! For arrays template<typename T, typename R, size_t Size> struct Euclidean<R, T[Size]> { using Type = T[Size]; static inline R Distance(Type q, Type p) { R RetVal = R(); for (auto i = 0u; i < Size; ++i) { RetVal += (q[i] - p[i]) * (q[i] - p[i]); } return static_cast<R>(std::sqrt(RetVal)); } }; //! For containers template< template<typename> typename T, typename R> struct Euclidean<T<R>, R> { static inline R Distance(T<R> q, T<R> p) { R RetVal = R(); for (auto i = 0u; i < std::size(q); ++i) { RetVal += (q[i] - p[i]) * (q[i] - p[i]); } return static_cast<R>(std::sqrt(RetVal)); } }; int main() { float q[4] = { 1,2,3,4 }; float p[4] = { 5,6,7,8 }; using TVectori = std::array<unsigned int, 4u>; std::vector<float> qv = { 5,6,7,8 }; std::vector<float> pv = { 5,6,7,8 }; std::array<float, 4u> qa = { 5,6,7,8 }; std::array<float, 4u> pa = { 5,6,7,8 }; std::cout << Euclidean<float, float>::Distance(4.f, 5.f) << std::endl; std::cout << Euclidean<float, float[4]>::Distance(q, p) << std::endl; std::cout << Euclidean<std::vector<float>, float>::Distance(qv, pv) << std::endl; std::cout << Euclidean<std::array<float, 4u>, float>::Distance(qa, pa) << std::endl; std::cin.get(); return 0; } У меня почему то пытается вызваться базовая версия шаблона. Спасибо. |
Сообщ.
#2
,
|
|
|
Я думаю тебе должна помочь эта статейка.
|
Сообщ.
#3
,
|
|
|
Цитата Wound @ Не получается сделать специализацию для контейнеров. Для массива работает, для std::array/std::vector не хочет. У std::vector два параметра шаблона. Надо делать template< template<typename, typename> typename T, typename R> или что-то типа того |
Сообщ.
#4
,
|
|
|
Сообщ.
#5
,
|
|
|
Цитата Олег М @ У std::vector два параметра шаблона. Надо делать template< template<typename, typename> typename T, typename R> или что-то типа того Пробовал, тогда не понятно что передавать в список аргументов: template< template<typename, typename> typename T, typename R> struct Euclidean<T<R, ?>, R> { static inline R Distance(const T<R,?>& q, const T<R,?>& p) { R RetVal = R(); for (auto i = 0u; i < std::size(q); ++i) { RetVal += (q[i] - p[i]) * (q[i] - p[i]); } return static_cast<R>(std::sqrt(RetVal)); } }; Цитата JoeUser @ Я думаю тебе должна помочь эта статейка. Ща гляну. |
Сообщ.
#6
,
|
|
|
Цитата Wound @ Пробовал, тогда не понятно что передавать в список аргументов: struct Euclidean<T<R, std::allocator<R>>, R> |
Сообщ.
#7
,
|
|
|
Цитата Олег М @ struct Euclidean<T<R, std::allocator<R>>, R> Да, заработало. Спасибо. Добавлено А еще такой вопрос, вот по сути тут передается вектор и std::array, у которых два шаблонных параметра. Если переписывать на вариадики, то должно получится примерно вот так(чтоб не писать для каждого контейнера специализацию)? template< template<typename ...> typename T, typename R, typename ... Args> struct Euclidean<T<R, Args...>, R> { static inline R Distance(const T<R, Args...>& q, const T<R, Args...>& p) { R RetVal = R(); for (auto i = 0u; i < std::size(q); ++i) { RetVal += (q[i] - p[i]) * (q[i] - p[i]); } return static_cast<R>(std::sqrt(RetVal)); } }; Добавлено Не, для std::array вариадик не прокатил, только для вектора и ему подобных. Видимо все таки для std::array нужна отдельная специализация. Получилось вот так: template<typename T, typename R, std::size_t N> struct Euclidean<std::array<T, N>, R> { using TArray = std::array<T, N>; static inline R Distance(const TArray& q, const TArray& p) { R RetVal = R(); for (auto i = 0u; i < std::size(q); ++i) { RetVal += (q[i] - p[i]) * (q[i] - p[i]); } return static_cast<R>(std::sqrt(RetVal)); } }; template< template<typename ...> typename T, typename R, typename ... Args> struct Euclidean<T<R, Args...>, R> { using TContainer = T<R, Args...>; static inline R Distance(const TContainer& q, const TContainer& p) { R RetVal = R(); for (auto i = 0u; i < std::size(q); ++i) { RetVal += (q[i] - p[i]) * (q[i] - p[i]); } return static_cast<R>(std::sqrt(RetVal)); } }; |
Сообщ.
#8
,
|
|
|
Цитата Wound @ template< template<typename ...> typename T, typename R, typename ... Args> struct Euclidean<T<R, Args...>, R> { static inline R Distance(const T<R, Args...>& q, const T<R, Args...>& p) { R RetVal = R(); for (auto i = 0u; i < std::size(q); ++i) { Здесь лучше делать через итераторы - begin/end, а то для std::list не будет работать, да и размерность массивов может быть разная. |