2012-11-14 25 views
1

我需要一系列具有可變數量值的初始化函數。我正在使用它們來執行Eigen庫的收集操作。下面是我對每個向量長度的一個模板,做它現在的方式:可變長度初始值設定程序的模板

template<typename T1, typename T2> 
inline void gather (Array<T1,4,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,4,1> &index) 
{ 
    to << from[index[0]], from[index[1]], from[index[2]], from[index[3]]; 
} 

template<typename T1, typename T2> 
inline void gather (Array<T1,6,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,6,1> &index) 
{ 
    to << from[index[0]], from[index[1]], from[index[2]], from[index[3]], from[index[4]], from[index[5]]; 
} 

有沒有一種方法,以取代像上面用長度參數參數化的一個模板模板較長列表(4和上面的代碼片段6)?如果是這樣,是否可以使用C++ 11語言規範(我正在使用Visual Studio 2010)?

我想保留逗號分隔值語法,因爲我希望它在某些情況下可能會產生編譯時初始化(常量fromindex)。雖然我可能在這個假設上是錯誤的。初始化程序列表可以有1到16個值 - 不需要擔心空列表。

+0

我認爲你正在尋找一種方法來做到這一點與自動演繹,是嗎?另外,這是否應該是一個插入鏈(對於<< val << val << val ..)或是所有意圖的逗號? – WhozCraig

+0

逗號是必需的 - 這是Eigen初始化程序的語法。我希望它會產生編譯時初始化。 –

+0

有可能這樣做是在編譯時進行初始化,因爲你正在處理已經初始化的數據。 – Xeo

回答

2

不要在此設置中使用逗號初始值設定項語法,這將是繁瑣的。在使用文字時,此語法用於可讀性,這不是您的情況。

相反,我建議是這樣的:

template<typename T1, typename T2, unsigned int SIZE, unsigned int INDEX> 
struct gather { 
    gather(Array<T1,SIZE,1> &to, 
      const Array<T2,Dynamic,1> &from, 
      const Array<int,SIZE,1> &index) 
    { 
     to.col(INDEX) = from[index[INDEX]]; 
     gather<T1,T2,SIZE,INDEX+1>(to,from, index); 
    } 
}; 

template<typename T1, typename T2, unsigned int SIZE> 
struct gather<T1,T2,SIZE,SIZE>{ 
    gather(Array<T1,SIZE,1> &to, 
      const Array<T2,Dynamic,1> &from, 
      const Array<int,SIZE,1> &index) 
    { 
    } 
}; 

這很好地產生相同的效果,但靜態(無迴路)。

我在這裏使用了一個結構,因爲函數的局部模板專門化限制,但它應該歸結爲相同的,因爲內聯。

+0

似乎'CommaInitializer'不能執行編譯時初始化,所以這個解決方案甚至循環解決方案(答案已被刪除)都可以。 –

2

基於重載operator,運算符來概括此語法是相當棘手的,結果看起來很尷尬(如果它有效)。我會建議嘗試其他選項(例如去MatrixBase::operator<<(DenseBase&)運營商)。

如果你想要的是,你必須解開標量一個接一個:

template<typename T1, typename T2, class CI, int Current, int Height> 
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Current>*) 
{ 
    gather(to, from, index, (ci,from[index[Current]]), (std::integral_constant<int, Current+1>*)0); 
} 

template<typename T1, typename T2, class CI, int Height> 
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index, CI&& ci, std::integral_constant<int, Height>*) {} 

template<typename T1, typename T2, int Height> 
inline void gather (Array<T1,Height,1> &to, const Array<T2,Dynamic,1> &from, const Array<int,Height,1> &index) { 
    gather(to, from, index, (to << index[from[0]]), (std::integral_constant<int, 1>*)0); 
} 

醜,可能有問題(你需要處理Dynamic值,零高度,如果可能的話,可能有問題通過CommaInitializers遞歸等)

另外,它具有線性模板實例化深度(和恕我直言,在這種情況下是不可避免的)。

+0

@jplacek零元素不是問題 - 我編輯了我的問題。我同意,這是醜陋的:-)最重要的是,我只有一個微弱的線索,說明它的實際作用。 –

相關問題