2014-10-09 58 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>; 

這是模擬SI單元的庫的(部分)。你只能乘以不同的單位,你可以額外添加像單位和標量。這些庫很簡單,因爲如果你不適當地混合單元,它們會導致編譯時錯誤。有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。組織/ DOC /庫/ 1_56_0/DOC/HTML/boost_units.html)? – dyp 2014-10-09 00:48:59

+0

*「你只能乘以不同的單位」*所以,沒有平方米,沒有m /s²等?爲什麼? – dyp 2014-10-09 00:50:14

+0

下面是一對元組變換的簡單示例:http://coliru.stacked-crooked.com/a/e5f03a72538ce8c5由於這是類型列表的基本功能,因此您可以在許多TMP庫中找到一些實現。我在我的例子中使用的接口非常尷尬(但它與'std :: ratio_add'很好地集成在一起);我建議你嘗試使用'constexpr'函數。 – dyp 2014-10-09 01:04:39

回答

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 2014-10-09 12:00:34

+0

我明白這一點,但男人,我的企圖遠沒有接近這一點。你有鏈接到我可以學習的資源嗎? @dyp,我希望你沒有刪除你的答案。如果它有效,我還是希望看到它。我正在努力學習這些東西,並提升我的技能。 – 2014-10-09 15:17:09

+0

@MthetheReddington Huh?我從來沒有在這裏發佈答案..我只在你的問題下面留下了一個實現鏈接的評論.. – dyp 2014-10-09 15:28:56

-1

我沒有足夠的信息,但它看起來像(1,0,-2,0,0,0,0)將是加速所需的。 1表示米,-2表示除以秒的平方,就像數學中的負指數一樣。

+1

這與這個問題有什麼關係? – 2014-10-09 04:38:17

+0

速度是速度方程的一階導數,加速是第二個,它們不是同一個東西。但是,是的,你是絕對正確的。 – 2014-10-09 15:05:44

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;