2014-05-04 86 views
3

如果我想的指針設置爲一個多維C++數組的第一個元素,我可以很容易地做到這一點:一般地獲得一個指向多維C++數組的第一個元素

double arr[2][3][4]; 
double *p; 
p = &arr[0][0][0]; 

哪有我這樣做是爲了任意級別的數組?

template <typename T, unsigned N> 
void receive(T (&a)[N]) {} 

的C++ 11 std::remove_all_extents類模板可以用來獲得的陣列的(最深)元素:A型功能接收到一個多維數組的引用可以如下被寫入。這可以幫助使用typename std::remove_all_extents<T>::type *構建修改版本receive的返回類型。但是如何創建返回的

以下解決方案使用reinterpret_cast。這大概會被有效執行,但我不喜歡reinterpret_cast的類型系統的規避。

template <typename T, unsigned N> 
typename std::remove_all_extents<T>::type * 
to_ptr1(T (&a)[N]) { return reinterpret_cast< 
           typename std::remove_all_extents<T>::type * 
          >(&a); } 

替代地,下面的解決方案使用遞歸,並且當類型系統保持強,遞歸可能引入額外的指令。

template <typename T> T *to_ptr2(T &a) { return &a; } 

template <typename T, unsigned N> 
typename std::remove_all_extents<T[N]>::type * 
to_ptr2(T(&a)[N]) { return to_ptr2(*(&a[0])); } 

如何獲得一個多維數組的第一個元素的地址?有零開銷的強類型解決方案嗎?

+0

「reinterpret_cast」的解決方案中沒有強類型?這是國際海事組織的罰款,我不認爲它會比這更好。 – jrok

+0

我不習慣元編程魔法,但我很確定解決方案涉及['std :: rank'](http://en.cppreference.com/w/cpp/types/rank)。 –

+0

「reinterpret_cast」版本沒有問題 - 數組保證沒有初始填充。我想知道'remove_all_extents'是否還沒有通過遞歸模板實現。 –

回答

0
#include <iostream> 
#include <type_traits>  

template<size_t Rank> 
struct deref_n 
{ 
    template<typename T> 
    auto operator()(T& ptr) -> decltype(deref_n<Rank-1>()(*ptr)) 
    { 
     return deref_n<Rank-1>()(*ptr); 
    } 
}; 

template<> 
struct deref_n<0> 
{ 
    template<typename T> 
    T& operator()(T& val) 
    { 
     return val; 
    } 
}; 

template<typename T> 
auto first_element(T& val) -> decltype(deref_n<std::rank<T>::value>()(val)) 
{ 
    return deref_n<std::rank<T>::value>()(val); 
} 


int main() 
{ 
    int x[10][20][30] = {}; 
    first_element(x) = 777;    // this gives me a reference to x[0][0][0] 
    std::cout << x[0][0][0] << '\n'; 
} 
+0

謝謝本傑明。唉這似乎遵循一個非常相似的遞歸方案來'to_ptr2'從原來的問題。 – user2023370

+0

模板遞歸可能會在編譯時被解析...嘗試檢查編譯器生成的程序集,如果這涉及到你 –

+0

嗨馬特。我只關心最好的解決方案。如果一個遞歸策略總是意味着我應該檢查程序集,這會影響它。 – user2023370

相關問題