2017-03-17 59 views
6

我想有效地從參數包與一個std ::數組的元素相乘的參數:C++ 17有效地乘以參數包參數與標準::陣列元件

int index(auto... Is, std::array<int,sizeof...(Is)> strides) 
{ 
    // pseudo-code 
    // int idx = 0; 
    // for(int i = 0; i < sizeof...(Is); ++i) 
    // idx += Is[i] * strides[i]; 
    // return idx; 
} 

我不能把我的大腦圍繞在這個問題上。我開始了一個索引序列的道路,但我可以想出如何合併總和。

我正在使用C++ 17,因此如果他們會簡化代碼,摺疊表達式就是公平的遊戲。

感謝您的指點。

編輯:澄清僞代碼。唯一的僞部分是表達式Is[i],它是指第i個參數包參數。

TC的下面的答案是完美的,這是我最後的代碼是一個成員函數:

unsigned int index(auto... indexes) 
{ 
    unsigned int idx = 0, i = 0; 
    (..., (idx += indexes * m_strides[i++])); 
    return idx; 
} 

在撰寫本文時,代碼編譯使用gcc 6.3.0與-fconcepts標誌,帶來概念TS。

使用auto... indexestemplate<typename Args> f(Args... indexes)的簡寫。我試圖爲參數使用unsigned int概念,但是我無法讓它工作。

的(...)折是關鍵要素,擴展到類似的信息(如果你能真正[]進入參數包):

idx += indexes[0] * m_strides[i++], idx += indexes[1] * m_strides[i++], etc. 

那是我缺少的洞察力。

+0

我很好奇,你所使用的編譯器。 – ThomasMcLeod

+0

@ThomasMcLeod gcc 6.3.0 - 具有摺疊表達式和一些其他C++ 17功能。 – RandomBits

+1

@ThomasMcLeod GCC 7是C++ 17完成的(不是libstdC++雖然) –

回答

3

我不能得到auto...工作,所以我改變了index的簽名。

您需要一個輔助功能(index_helper)才能使用index_sequence,因爲它依靠模板參數推導來填充索引。

#include <array> 
#include <cstdio> 

template <typename... T, size_t... i> 
//      ^~~~~~~~~~~ 
//      use deduction to make {i...} = {0, 1, 2, ..., n} 
static int index_helper(const std::array<int, sizeof...(T)>& strides, 
         std::index_sequence<i...>, 
         T... Is) 
{ 
    return (0 + ... + (strides[i] * Is)); 
} 

template <typename... T> 
int index(const std::array<int, sizeof...(T)>& strides, T... Is) { 
    return index_helper(strides, std::make_index_sequence<sizeof...(T)>(), Is...); 
//        ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 
//        generates {0, 1, 2, ..., n} 
} 

int main() { 
    printf("%d\n", index({1, 100, 100000, 1000}, 2, 3, 5, 7)); 
    // 507302 
} 
+0

鑑於所涉及的類型,無法使其成爲「constexpr」。 : - ] – ildjarn

1

如果你能倒錘的參數包成一個單一的類型,它是廉價的複製/移動,你可以使它成爲一個數組:

T arr[] = { static_cast<T>(Is)... }; // for some T, possibly common_type_t<decltype(Is)...> 

然後,你可以把你的僞代碼變成真實的代碼。

如果這不可行,逗號倍,可以用:

int idx = 0, i = 0; 
(..., (idx += Is * strides[i++])); 
return idx; 
+0

我沒有意識到你可以在這樣的摺疊中使用和修改索引變量。這很有用。 – RandomBits