По сути, вопрос , если вы можете использовать ссылки в контейнерах . Конечно, вы можете ЕСЛИ правильно подготовить свой класс И свой контейнер. Ниже я продемонстрирую это с двумя простыми векторными контейнерами: vectoref
, который изменяет std::vector<>
, и другой, vec
, который реализован с нуля.
#include <iostream>
#include <vector>
// requires compilation with --std=c++11 (at least)
using namespace std;
class A {
int _a; // this is our true data
A *_p; // this is to cheat the compiler
public:
A(int n = 0) : _a(n), _p(0)
{ cout << "A constructor (" << this << "," << _a << ")\n"; }
// constructor used by the initializer_list (cheating the compiler)
A(const A& r) : _p(const_cast<A *>(&r))
{ cout << "A copy constructor (" << this << "<-" << &r << ")\n"; }
void print() const {cout << "A instance: " << this << "," << _a << "\n";}
~A() {cout << "A(" << this << "," << _a << ") destructor.\n";}
// just to see what is copied implicitly
A& operator=(const A& r) {
cout << "A instance copied (" << this << "," << _a << ")\n";
_a = r._a; _p = r._p;
return *this;
}
// just in case you want to check if instance is pure or fake
bool is_fake() const {return _p != 0;}
A *ptr() const {return _p;}
};
template<typename T, int sz>
class vec { // vector class using initializer_list of A-references!!
public:
const T *a[sz]; // store as pointers, retrieve as references
// because asignment to a reference causes copy operator to be invoked
int cur;
vec() : cur(0) {}
vec(std::initializer_list<T> l) : cur(0) {
cout << "construct using initializer list.\n";
for (auto& t : l) // expecting fake elements
a[cur++] = t.ptr();
}
const T& operator[](int i) {return *a[i];}
// expecting pure elements
vec& push_back(const T& r) {a[cur++] = &r; return *this;}
void copy_from(vec&& r) {
for (int i = 0; i < r.cur; ++i)
push_back(r[i]);
}
};
template<typename T>
class vectoref : public vector<T *> { // similar to vec but extending std::vector<>
using size_type = typename vector<T*>::size_type;
public:
vectoref() {}
vectoref(std::initializer_list<T> l) {
cout << "construct using initializer list.\n";
for (auto& t : l) // expecting fake elements
vector<T*>::push_back(t.ptr());
}
const T& operator[](size_type i) {return *vector<T*>::at(i);}
// expecting pure elements
vectoref& push_back(const T& r)
{ vector<T*>::push_back(&r); return *this; }
void copy_from(const vectoref&& r) {
for (size_type i = 0; i < r.size(); ++i)
vectoref<T>::push_back(r[i]);
}
};
class X { // user of initializer_list of A
public:
X() {}
void f(initializer_list<A> l) const {
cout << "In f({...}):\n";
for (auto& a : l)
a.ptr()->print();
}
};
int main()
{
A a(7), b(24), c(80);
cout << "----------------------------------\n";
vectoref<A> w{a,a,b,c}; // alternatively, use next line
// vec<A,5> w{a,a,b,c}; // 5-th element undefined
w[0].print();
w[3].print();
cout << "----------------------------------\n";
X x;
x.f({a,b,c,a,b,c,b,a});
cout << "==================================\n";
return 0;
}