2012-02-10 46 views
4

我知道如何編寫一個接受可變數量的參數的可變參數模板功能:傳遞可變數量的引用到陣列與可變參數模板功能

template<int I, typename... Rest> 
void f() { 
    // whatever 
} 

,我知道如何寫模板函數接受一個數組的引用:

template<typename T, unsigned int Length> 
void f(T(&arr)[Length]) { 
    // whatever 
} 

,但我想不出如何讓函數接受不定數量的數組引用將兩者結合起來。

我第一次嘗試是

template<typename T, unsigned int Length> 
unsigned int arrlen(T(&)[Length]) { 
    return Length; 
} 

template<typename T, unsigned int Length> 
int f(T(&arr)[Length]) { 
    return Length; 
} 

template<typename T, unsigned int Length, typename... Rest> 
int f(T(&arr)[Length], Rest... rest) { 
    return Length + f(rest...); 
} 

int main() { 
    int a[] = {1 , 2, 3}, b[] = {1, 2, 3, 4, 5}, c[] = {1}; 

    cout << f(a, b, c); 
} 

但是,編譯器告訴我

a.cpp: In function 'int f(T (&)[Length], Rest ...) [with T = int, unsigned int Length = 3u, Rest = {int*, int*}]'

a.cpp:23:22: instantiated from here

a.cpp:17:27: error: no matching function for call to 'f(int*&, int*&)'

a.cpp:17:27: note: candidates are:

a.cpp:11:22: note: template int f(T(&)[Length])

a.cpp:16:5: note: template int f(T(&)[Length], Rest ...)

所以我在想,你可以寫,將其存儲與構建數組的長度的對象,然後傳遞可變數量的那些(這將從傳遞的數組中隱式構造)到函數中。這是我嘗試做的是:

template<typename T, unsigned int Length> 
struct Array { 
    Array(T(&arr)[Length]) : arr(arr), len(Length) { } 

    T(&arr)[Length]; 
    const unsigned int len; 
}; 

int f() { 
    return 0; 
} 

template<typename T, unsigned int Length, typename... Args> 
int f(const Array<T, Length>& a1, Args... rest) { 
    return a1.len + f(rest...); 
} 

int main() { 
    int a[] = { 1, 2, 3 }, b[] = { 1, 2, 3, 4, 5 }, c[] = { 1 }; 

    cout << f(a, b, c); 
} 

但是,當我嘗試用GCC 4.6.1編譯它,我得到的錯誤

a.cpp: In function 'int main()':

a.cpp:27:22: error: no matching function for call to 'f(int [3], int [5], int [1])'

a.cpp:27:22: note: candidates are:

a.cpp:16:47: note: template int f(const Array&, Args ...)

a.cpp:20:5: note: int f()

a.cpp:20:5: note: candidate expects 0 arguments, 3 provided

然而,除了固定的第二代碼(這更多的是一種解決方法是不知道如何去做我真正想做的事),這個問題的實際點和我真正想學的東西是如何在不使用代理對象的情況下做到這一點,如果可能的話,就像第一個代碼一樣。那麼這怎麼做呢?在我發佈的其中一個嘗試中是否有簡單的語法錯誤?

+0

只要使用'的std :: array',忘記原AR ray廢話。 – 2012-02-10 18:04:53

+2

@CatPlusPlus這將是簡單的出路,並不會幫助我瞭解這裏發生了什麼。 – 2012-02-10 18:06:21

+0

@CatPlusPlus和實際上會出現相同的問題 – 2012-02-10 18:13:47

回答

3

如果你只是想總結了一些列的長度,你可以直接做到這一點:

template<typename T, unsigned int Length> 
int f(const T (&)[Length]) { 
    return Length; 
} 

template<typename T, unsigned int Length, typename... Args> 
int f(const T (&)[Length], Args&... rest) { 
    return Length + f(rest...); 
} 

int main() { 
    int a[] = { 1, 2, 3 }, b[] = { 1, 2, 3, 4, 5 }, c[] = { 1 }; 

    std::cout << f(a, b, c); 
} 
+0

那麼我唯一缺少的東西就是'Args'前面的'&'? – 2012-02-10 18:09:03

+0

@SethCarnegie:當然,背後呢? – 2012-02-10 18:10:45

+1

@LightnessRacesinOrbit取決於單詞所面對的方向:) – 2012-02-10 18:11:31

2

您可以使用std::extent得到一個數組的外部尺寸的程度,variadically總結這些了:

#include <type_trait> 

template <typename Arr, typename ...Rest> struct extent_sum 
: std::integral_constant<std::size_t, 
         std::extent<T>::value + extent_sum<Rest...>::value> { }; 

template <typename T> struct extent_sum<T> 
: std::integral_constant<std::size_t, std::extent<T>::value> { }; 

用法:

const std::size_t n = extent_sum<int[2], char[4], float[3], bool>::value; 
+0

Kerrek,'constexpr'應該是首選(從GCC 4.6 AFAIR開始):[「想要速度?使用constexpr元編程!」](http://cpptruths.blogspot.com/2011/07/want-speed-使用-constexpr-meta.html)。 – 2012-02-10 18:43:44