Есть ли способ реализовать списки инициализатора (вид) в более старой версии C ++ (до C ++ 11)? - PullRequest
3 голосов
/ 28 мая 2019

Я пытался реализовать (вроде :) Списки инициализаторов в более старой версии c ++.как показано ниже ..

#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;
}

Но этот вид реализации работает в Visual studio 2012 (v11.0).Но не в Linux G ++ компилятор.И закончился ошибкой: «не может передать объекты типа« Test Test »с нетривиально копируемым типом через« ... »»

Так есть ли лучшая идея?

Ответы [ 2 ]

1 голос
/ 28 мая 2019

Если вы готовы принять немного другой синтаксис, тогда все, что вам нужно, это версия vector::push_back(), которая возвращает ссылку на вектор. Как то так:

#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;
}

Также на ум приходят рекурсивные шаблоны, но я не уверен, насколько чист с ними будет синтаксис. См. Также этот вопрос о перегрузке оператора запятой.

0 голосов
/ 29 мая 2019

То же, что и этот ответ выше, Даниэль Но некоторые улучшения

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;}
};

Использование

    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);
...