I wanted to write a simple container / factory and prohibit the creation of an object in other ways, but I ran into an unexpected problem. Simplified code:

struct MyObject { friend struct MyObjectContainer; private: MyObject(int param) { _param = param; } int _param; }; struct MyObjectContainer : private std::vector<MyObject> { void Add(int param) { emplace_back(param); } } objs; 

The compiler gives an error:

c: \ program files (x86) \ microsoft visual studio 14.0 \ vc \ include \ xmemory0 (637): error C2248: 'MyObject :: MyObject': 'MyObject'

When replacing emplace_back (param) with push_back (MyObject (param)), the code works, but I would like to find a way to use a more rational method of emplace_back.

  • Why MyObjectContainer Friend for MyObject? Why is the constructor private? You and the vector inherited privately. - Sublihim

2 answers 2

You need to register a friend for std :: allocator, since it is this template that creates your class.

 struct MyObject { friend class std::allocator<MyObject>; ... 
  • Then it makes no sense to use emplace_back, since it will be easier to write push_back, as already indicated in the question. - Vlad from Moscow
  • Well, so for MyObject friendly MyObjectContainer and not a vector. Such excessive closeness will create more problems for the code. - Sublihim
  • Your solution does not work under gcc. There you need to write something like friend class __gnu_cxx::new_allocator<MyObject>; - 伪位蔚蠂慰位蠀蟿
  • Thanks for the answer, the variant is working (it also came up for std :: queue and std :: deque). But with std :: list and std :: forward_list, unfortunately, it does not compile (it writes the same error), can you know how to win? ) - Aleksey Sokolov
  • @AlekseySokolov compiler you need to write which class the private constructor is trying to call. clang for example, said the following: std::__1::allocator<std::__1::__list_node<MyObject, void *> > . But this is all very crooked, although it makes the code compilable. I recommend not to create problems out of the blue. The approach of my answer successfully works for all types of standard containers. - 伪位蔚蠂慰位蠀蟿

If only MyObject access to MyObjectContainer , then it鈥檚 more logical to simply make it a nested class in a private section. At the same time, inheritance is replaced by aggregation:

 struct MyObjectContainer { void Add(int param) { v.emplace_back(param); } private: struct MyObject { MyObject(int param) { _param = param; } int _param; }; std::vector<MyObject> v; } objs;