Reputation: 1167
i have tried to implement (kind of :) Initializer lists in older version of c++. like below..
#include <vector>
#include <cstdarg>
#include <iostream>
using namespace std;
template <class T>
vector <T> VEC_VA(size_t argCount,T arg1, ... )
{
va_list arguments;
vector <T> sList;
va_start ( arguments, argCount);
for ( int x = 0; x < (int)argCount; x++ )
sList.push_back(va_arg ( arguments, T));
va_end ( arguments );
return sList;
}
struct Test
{
Test(int _x,std::string _s):x(_x),s(_s){}
int x;
std::string s;
};
void methodWithArgs(vector<Test> testObjs)
{
cout<<"Size:"<<testObjs.size()<<endl;
for (std::vector<Test>::const_iterator it = testObjs.begin();it != testObjs.end();++it)
std::cout << it->x <<":"<< it->s.c_str()<< std::endl;
}
int main()
{
methodWithArgs(VEC_VA(2,Test(1,"one"),Test(2,"two")));
return 0;
}
But this kind of implementation works in Visual studio 2012 (v11.0). But not in Linux g++ compiler. And ended with an Error: "cannot pass objects of non-trivially-copyable type ‘struct Test’ through ‘...’"
So is there any better idea?
Upvotes: 3
Views: 132
Reputation: 1167
Same as like this above answer by daniel But some improvements
template <class T>
class VECS
{
vector <T> vec;
public:
VECS(){}
VECS(T t){vec.push_back(t);}
VECS& operator()(const T& t){vec.push_back(t);return *this;}
typedef VECS<T> myVECS;
myVECS& operator<< (const T& t){vec.push_back(t);return *this;}
operator vector<T>() const {return vec;}
};
Usage
methodWithArgs(VECS<Test>(Test(1,"one"))(Test(2,"two")));
methodWithArgs(VECS<Test>()<<Test(1,"one")<<Test(2,"two"));
methodWithArgs(VECS<Test>(Test(0,"zero")) <<Test(1,"one")<<Test(2,"two"));
std::vector<int> v1 = VECS<int>() << 1 << 2 << 3;
std::vector<int> v2 = VECS<int>(1)(2)(3);
Upvotes: 0
Reputation: 5950
If you are willing to accept a slightly different syntax then all you need is a version of vector::push_back()
that returns a reference to the vector. Something like this:
#include <vector>
#include <iostream>
template<typename T>
class VEC_VA_HELP {
std::vector<T> vector;
public:
VEC_VA_HELP(T arg1) : vector() { vector.push_back(arg1); }
VEC_VA_HELP &operator()(T arg) { vector.push_back(arg); return *this; }
operator std::vector<T> &() { return vector; }
};
template<typename T>
VEC_VA_HELP<T> VEC_VA(T arg1) { return VEC_VA_HELP<T>(arg1); }
struct Test {
Test(int _x) : x(_x) {}
int x;
};
void methodWithArgs(std::vector<Test> const &testObjs) {
std::cout << testObjs.size() << std::endl;
for (std::vector<Test>::const_iterator it = testObjs.begin();
it != testObjs.end();
++it)
std::cout << it->x << std::endl;
}
int
main(void)
{
methodWithArgs(VEC_VA(Test(1))(Test(2))(Test(3)));
return 0;
}
Also recursive templates come to mind but I am not sure how clean the syntax would be with them. See also this question about overloading the comma operator.
Upvotes: 1