#include <cstdio> #include <iostream> #include <string> #include <vector> #include <mutex> #include <thread> #include <chrono> using namespace std; using namespace std::chrono_literals; template <typename T> class MyVector { private: struct DataWrapper { vector<T>& data_ref; mutex& data_mutex_ref; const size_t index; DataWrapper(vector<T>& dr, mutex& dmr, const size_t idx) : data_ref(dr), data_mutex_ref(dmr), index(idx) {} DataWrapper(const DataWrapper&) = default; ~DataWrapper() = default; DataWrapper& operator= (const DataWrapper&) = default; DataWrapper& operator= (const T& rhs); operator T () const; }; public: DataWrapper operator[] (const size_t index); private: typedef lock_guard<mutex> lock_type; vector<T> data; mutex data_mutex; }; template <typename T> typename MyVector<T>::DataWrapper MyVector<T>::operator[] (const size_t index) { if (index >= this->data.size()) { lock_type lock(this->data_mutex); if (0 != index) { this->data.resize(index << 1); } else { this->data.resize(1); } } return DataWrapper(this->data, this->data_mutex, index); } template <typename T> typename MyVector<T>::DataWrapper& MyVector<T>::DataWrapper::operator= (const T& rhs) { lock_type lock(this->data_mutex_ref); this->data_ref.at(this->index) = rhs; return *this; } template <typename T> MyVector<T>::DataWrapper::operator T () const { lock_type lock(this->data_mutex_ref); return this->data_ref.at(this->index); } struct MyData { string name; size_t data; MyData() = default; MyData(const char* n, const size_t d) : name(n), data(d) {} string tostr() const { return ("name: " + name + "\ndata: " + to_string(data)); } }; MyVector<MyData> buffer; void read(const size_t total) { for (size_t i = 0; i < total; ++i) { std::this_thread::sleep_for(50ms); MyData x = buffer[i]; // valid, calling casting operator // invalid, it will try to find a member function 'tostr' in MyVector<T>::DataWrapper but not in MyData // after casting the return type MyVector<T>::DataWrapper to MyData& //cout << buffer[i].tostr() << '\n'; cout << static_cast<MyData&>(buffer[i]).tostr() << '\n'; } } void write(const size_t total) { for (size_t i = 0; i < total; ++i) { buffer[i] = MyData("MyData", i + 1); std::this_thread::sleep_for(50ms); } } int main() { constexpr size_t TOTAL = 15; thread tw(write, TOTAL); thread tr(read, TOTAL); tw.join(); tr.join(); return 0; }