2014-10-09 1 views
1

Если вы отслеживаете мою историю вопроса, я обновляю библиотеку пространственного анализа ради того, чтобы качать кошмар макросов и изучать C++ 11, вариативные шаблоны, и метапрограммирование и парадигмы функционального программирования. Для моей жизни это все еще волшебство.Попытка суммировать две последовательности целочисленного набора времени компиляции

Во всяком случае, у меня есть кортежи констант экспоненты, которые определяют физические единицы.

template<int... I> 
using make_dimension = std::tuple<std::ratio<I>...>; 

using scalar_dimension = make_dimension<0, 0, 0, 0, 0, 0, 0>; 
using length_dimension = make_dimension<1, 0, 0, 0, 0, 0, 0>; 
using time_dimension = make_dimension<0, 0, 1, 0, 0, 0, 0>; 

Это (часть) библиотеки, которая моделирует единицы СИ. Вы можете умножать только единицы, в отличие от единиц, вы можете дополнительно добавить единицы и скаляры. Эти библиотеки денди в том, что они вызывают ошибки во время компиляции, если вы неправильно смешиваете блоки. Есть> 400 единиц, и большинство из них определяются с точки зрения других единиц. При умножении единиц измерения экспоненты добавляются, а при разделении единиц экспоненты вычитаются. Таким образом, чтобы определить скорость, я хотел бы средством выражения:

using velocity_dimension = divide_dimensions<length_dimension, time_dimension>; 

И это должно быть функционально эквивалентно записи:

using velocity_dimension = make_dimension<1, 0, -1, 0, 0, 0, 0>; 

Я погуглить, но я просто не знаю, терминология, чтобы приземлить некоторые хиты. Самое близкое, что я нашел, - это for_each, который применяет функцию к элементам кортежа во время выполнения ... И это как бы раздувает мой разум, поэтому я не могу понять, как превратить его в итерацию времени компиляции элементы. «make_dimension» выше было объяснено мне минуту назад, и это взорвало мой разум, но я выздоровел. Я как бы прошу просить раздаточный материал, и у кого-нибудь есть хорошие ресурсы для изучения этого материала? Я с трудом верю, что я единственный, кто очень заинтересован в этом.

+0

Принимали ли вы посмотрите на [ 'boost.units' библиотеки] (Http: //www.boost. орг/док/ЛИЭС/1_56_0/DOC/HTML/boost_units.html)? – dyp

+0

* «Вы можете размножать только разные единицы» * Итак, нет м², нет m/s² и т. Д.? Зачем? – dyp

+0

Вот краткий пример преобразования для пары кортежей: http://coliru.stacked-crooked.com/a/e5f03a72538ce8c5 Поскольку это базовая функция для списков типов, вы найдете некоторую реализацию во многих библиотеках TMP.Интерфейс, который я использовал в моем примере, довольно неудобен (но он прекрасно сочетается с 'std :: ratio_add'); Я бы предложил вам попробовать использовать 'constexpr' функции. – dyp

ответ

2

@ Решение dyp в комментариях использует рекурсивно созданный шаблон. Несмотря на то, что это одна из наиболее общих методов переменных числа шаблонов, в этом случае рекурсия, вероятно, излишняя, поскольку весь набор преобразований может быть выполнен в одном пакете расширении, который расширяет два параметра пакеты одновременно:

template<template<class, class> class, class, class> 
struct tuple_transform; // undefined 

template<template<class, class> class Transform, class...Ts, class...Vs> 
struct tuple_transform<Transform, std::tuple<Ts...>, std::tuple<Vs...>> { 
    using type = std::tuple<Transform<Ts, Vs>...>; 
}; 

template<class T, class U> 
using divide_dimensions = typename tuple_transform<std::ratio_subtract, T, U>::type; 

Обратите внимание, что вышесказанное предполагает, что Transform<T, U> является псевдонимом для желаемого результирующего типа. Это соответствует поведению ratio_add и т. Д. - они являются шаблонами псевдонимов для полученного std::ratio, поэтому typename ratio_add<...>::type не требуется.

Demo.

+0

Ну, я просто не метапрограммировал через некоторое время, и мои навыки ржавые;) +1 – dyp

+0

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

+0

@MatthewReddington Да? Я никогда не писал ответ здесь. Я только оставил комментарий со ссылкой реализации ниже вашего вопроса .. – dyp

-1

У меня недостаточно информации, но похоже, что (1,0, -2,0,0,0,0) было бы то, что вам нужно для ускорения. 1 представляет метры, а-2 будет представлять собой разделение по секундам в квадрате, как это делает отрицательный показатель в математике.

+1

Что это касается вопроса? –

+0

Velocity - первая производная уравнения скорости, ускорение - второе, они не одно и то же. Но да, вы абсолютно правы. –

0

Ответ на вопрос T.C.s правильный, вы можете просто взять std::integer_sequence (который является C++ 14, но может быть просто реализован) вместо отношения и кортежа, которые (по моему мнению) не подходят и не используют конструктор constexpr для манипуляций. Теперь ваш код должен выглядеть следующим образом (я не пробовал компилировать):

template<int... I> 
using make_dimension = std::integer_sequence<int, I...>; 

template<class Functor, class Dim1, class Dim2> 
struct transfrom; 

template<class Functor, int... Dims1, int... Dims2> 
struct transform< 
    Functor, 
    std::integer_sequence<int, Dims1...>, 
    std::integer_sequence<int, Dims2...> 
> { 
    static_assert(sizeof...(Dims1)==sizeof...(Dims2), "wrong dimensions"); 
    static constexpr Functor f; 
    using type=std::integer_sequence<int, f(Dims1,Dims2)...>; 
}; 

struct add { 
    constexpr int operator()(int l, int r) const { return l+r; } 
}; 
struct sub { 
    constexpr int operator()(int l, int r) const { return l-r; } 
}; 

template<class T, class U> 
using divide_dimensions = typename transform<sub, T, U>::type; 
Смежные вопросы