auto can create instances of private classes
Solved
C++ Gurus
-
This really surprised me:
#include <QCoreApplication> #include <QDebug> #include <QString> #include <cmath> template<class T> class TestIndices { private: class InterOp { public: InterOp()=delete; //InterOp(InterOp&)=delete; // prevents copy constructor, we need it InterOp(TestIndices& obj, int index) :m_obj(obj), m_index(index) {} operator T(){ return m_obj.getValue(m_index); } InterOp& operator=(T const& value) { m_obj.setValue(m_index, value); return *this; } private: TestIndices& m_obj; int m_index; }; public: TestIndices(){} // T const& operator[](int index) const // { // qInfo() << "Reading value: " << index << m_data[index]; // return m_data[index]; // } InterOp operator[](int index){ qInfo() << "Create interop: " << index; return InterOp(*this, index); } private: void setValue(int index, T const& value){ qInfo() << "Writing value: " << index << value; m_data[index] = value; } T getValue(int index){ qInfo() << "Reading value: " << index << m_data[index]; return m_data[index]; } //private: public: QVector<T> m_data; }; int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); TestIndices<double> tind; tind.m_data.append(0.0); tind.m_data.append(1.0); tind.m_data.append(2.0); //TestIndices<double>::InterOp test = tind[1]; // cannot declare private variable auto test = tind[1]; // but auto can! qInfo() << typeid(test).name(); // N11TestIndicesIdE7InterOpE qInfo() << "a" << test; test = 3.0; qInfo() << "b" << test; auto test2 = tind[1]; qInfo() << "c" << test2; return a.exec(); }
Output:
Create interop: 1 N11TestIndicesIdE7InterOpE Reading value: 1 1 a 1 Writing value: 1 3 Reading value: 1 3 b 3 Create interop: 1 Reading value: 1 3 c 3
Apparently I cannot explicitly declare an instance of the private class, but "auto" can. I wonder if this is a potential problem or just a nice feature. This is C++ 11 btw.
Edit: Apparently it surprised other people too.
-
This feature allows to return values of "hidden" type from library which can be used only with
auto
or passed as an argument to some other library function.For example, standard library of C++17 introduces a concept of node handle, type of which is left as implementation detail and may be different between implementations or their versions. You can do a few operations with node handles, but cannot ever reference their "true" type.