[英]Constructor initilizer list for a class with multiple arrays (C++11 is ok, boost and std::vector are not)
[英]Converting C++11 code that depends on std::vector initialization list constructor
由於微軟不支持使用初始化列表來構造std::vector
一個很好的C ++ 11特性,遺憾的是我需要重構一些代碼以便與VS編譯器一起使用。
我能想到的最好方法是使用vector
的數組指針和長度構造函數 。 以前我做過這個:
MyClass(std::initializer_list<T> init):myStdVector(init){
這讓我做了很多好事:
MyClass hi({1,2,3,4});
我認為合適的物品數量可變。
如何通過直接傳遞數組來實現同樣的優雅? 是否可以在函數參數中實際初始化數組?
我能做到這一點:
MyClass(T*initArray,int arraySize):myStdVector(initArray,initArray+arraySize){
但是我必須這樣做:
int whatever[4]={1,2,3,4};
MyClass hi(whatever,4);
看起來很笨拙。 也許我錯過了一個更好的解決方案?
是的,使您的構造函數成為模板,並通過引用接受數組。 它需要是一個模板,因為數組長度將是推導出的參數: template<int N> MyClass::MyClass(int (&array)[N]) { }
。 當你傳遞int whatever[4]
,N顯然被推斷為4。
[編輯]在C ++ 11之前,代碼片段{1,2,3,4}
在數組和POD結構聲明之外沒有任何意義。 MyClass
既不是,也就是說有一個合適類型的聲明是不可避免的,並使用它來在下一行初始化MyClass
。
你可以用一些Boost.Preprocessor黑客攻擊:
#include <boost/preprocessor.hpp>
#define BOOST_PP_LOCAL_LIMITS /*mind the space here!*/ (1, 10) //where 10 is the max. number of arguments you can pass
// This macro will be expanded with maN ranging from 1 to 10 (as specified above)
#define BOOST_PP_LOCAL_MACRO(maN) \
template <class T> \
std::array<T, maN> make_array(BOOST_PP_ENUM_PARAMS(maN, T arg)) { \
std::array<T, maN> arr; \
BOOST_PP_REPEAT(maN, ASSIGN_ONE, %%) \
return arr; \
}
// BOOST_PP_REPEAT will expand this with maIdx randing from 0 to its first argument - 1 (maN-1 in your case)
#define ASSIGN_ONE(maZ, maIdx, maData) \-
arr[maIdx] = BOOST_PP_CAT(arg, maIdx);
// Performs the actual expansion
#include BOOST_PP_LOCAL_ITERATE()
// Usage:
template <size_t N>
MyClass(std::array<T, N> arr) : myStdVector(begin(arr), end(arr)) {}
int main() {
MyClass(make_array(1, 2, 3));
}
當然,您可以進一步定制它(例如直接為構造函數創建“variadic”重載等)。
您可以使用輔助函數來完成它,但是您必須提供長度,因此它不如initializer_list
版本那么好。 我還添加了另一個幫手( make_vec2
)。 如果您的編譯器支持該版本,則使用該版本,因為您不必手動指定該版本的數組長度。
#include <iostream>
#include <vector>
struct MyClass {
std::vector<int> v;
MyClass(std::vector<int> values) : v(values) {
}
};
template <std::size_t N>
std::vector<int>
make_vec(const int (&values)[N]) {
return std::vector<int>(values, values + N);
}
template <int... vs>
std::vector<int>
make_vec2() {
int tmp[] = { vs... };
return std::vector<int>(tmp, tmp + sizeof...(vs));
}
int main() {
MyClass mc(make_vec<4>({1, 2, 3, 4}));
MyClass mc2(make_vec2<1, 2, 3, 4>());
std::cout << mc.v.size() << "\n";
std::cout << mc2.v.size() << "\n";
return 0;
}
編輯 :您可以使用像MAKE_VEC(1, 2, 3, 4)
make_vec<4>({1, 2, 3, 4})
這樣的宏生成make_vec<4>({1, 2, 3, 4})
調用,但我傾向於遠離宏,因此該部分是離開作為練習。 另外,只需升級您的編譯器或使用另一個:)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.