从对象自己的静态成员函数中放置对象会产生"constructor declared private error"



在下面的片段中,我尝试从对象的静态成员函数(工厂方法(中实例化对象。我通过::template((将新创建的对象放入一个无序映射中,但这失败了,因为我希望构造函数是私有的(在实际上下文中,另一个静态成员函数调用Place((,它也是私有的(。

代码段

#include <unordered_map>
class Minimal
{
public:
static Minimal& Place(int id) {
static std::unordered_map<int, Minimal> collection;
auto it = collection.find(id);
if (it == end(collection)) {
it = collection.emplace(id, id).first;
}
return (*it).second;
}
private:
int id_;
Minimal(int id) : id_(id) {};        
};

int main()
{
Minimal::Place(2);
}

编译器错误(gcc 11.2(:

In file included from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/x86_64-linux-gnu/bits/c++allocator.h:33,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/allocator.h:46,
from /opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/unordered_map:40,
from <source>:1:
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ext/new_allocator.h: In instantiation of 'void __gnu_cxx::new_allocator<_Tp>::construct(_Up*, _Args&& ...) [with _Up = std::pair<const int, Minimal>; _Args = {int&, int&}; _Tp = std::__detail::_Hash_node<std::pair<const int, Minimal>, false>]':
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/alloc_traits.h:512:17:   required from 'static void std::allocator_traits<std::allocator<_Tp1> >::construct(std::allocator_traits<std::allocator<_Tp1> >::allocator_type&, _Up*, _Args&& ...) [with _Up = std::pair<const int, Minimal>; _Args = {int&, int&}; _Tp = std::__detail::_Hash_node<std::pair<const int, Minimal>, false>; std::allocator_traits<std::allocator<_Tp1> >::allocator_type = std::allocator<std::__detail::_Hash_node<std::pair<const int, Minimal>, false> >]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable_policy.h:1875:36:   required from 'std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_type* std::__detail::_Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&& ...) [with _Args = {int&, int&}; _NodeAlloc = std::allocator<std::__detail::_Hash_node<std::pair<const int, Minimal>, false> >; std::__detail::_Hashtable_alloc<_NodeAlloc>::__node_ptr = std::allocator<std::__detail::_Hash_node<std::pair<const int, Minimal>, false> >::value_type*]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable.h:289:35:   required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_Scoped_node::_Scoped_node(std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__hashtable_alloc*, _Args&& ...) [with _Args = {int&, int&}; _Key = int; _Value = std::pair<const int, Minimal>; _Alloc = std::allocator<std::pair<const int, Minimal> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _Hash = std::hash<int>; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__hashtable_alloc = std::_Hashtable<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::__hashtable_alloc]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable.h:1945:15:   required from 'std::pair<typename std::__detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::iterator, bool> std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::_M_emplace(std::true_type, _Args&& ...) [with _Args = {int&, int&}; _Key = int; _Value = std::pair<const int, Minimal>; _Alloc = std::allocator<std::pair<const int, Minimal> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _Hash = std::hash<int>; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; typename std::__detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::iterator = std::__detail::_Insert_base<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::iterator; typename _Traits::__constant_iterators = std::__detail::_Hashtable_traits<false, false, true>::__constant_iterators; std::true_type = std::integral_constant<bool, true>]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/hashtable.h:898:21:   required from 'std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__ireturn_type std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::emplace(_Args&& ...) [with _Args = {int&, int&}; _Key = int; _Value = std::pair<const int, Minimal>; _Alloc = std::allocator<std::pair<const int, Minimal> >; _ExtractKey = std::__detail::_Select1st; _Equal = std::equal_to<int>; _Hash = std::hash<int>; _RangeHash = std::__detail::_Mod_range_hashing; _Unused = std::__detail::_Default_ranged_hash; _RehashPolicy = std::__detail::_Prime_rehash_policy; _Traits = std::__detail::_Hashtable_traits<false, false, true>; std::_Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, _Hash, _RangeHash, _Unused, _RehashPolicy, _Traits>::__ireturn_type = std::_Hashtable<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::__ireturn_type]'
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/bits/unordered_map.h:389:23:   required from 'std::pair<typename std::_Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::__detail::_Select1st, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<std::__not_<std::__and_<std::__is_fast_hash<_Hash>, std::__is_nothrow_invocable<const _Hash&, const _Key&> > >::value, false, true> >::iterator, bool> std::unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>::emplace(_Args&& ...) [with _Args = {int&, int&}; _Key = int; _Tp = Minimal; _Hash = std::hash<int>; _Pred = std::equal_to<int>; _Alloc = std::allocator<std::pair<const int, Minimal> >; typename std::_Hashtable<_Key, std::pair<const _Key, _Tp>, _Alloc, std::__detail::_Select1st, _Pred, _Hash, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<std::__not_<std::__and_<std::__is_fast_hash<_Hash>, std::__is_nothrow_invocable<const _Hash&, const _Key&> > >::value, false, true> >::iterator = std::__detail::_Insert_base<int, std::pair<const int, Minimal>, std::allocator<std::pair<const int, Minimal> >, std::__detail::_Select1st, std::equal_to<int>, std::hash<int>, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, std::__detail::_Prime_rehash_policy, std::__detail::_Hashtable_traits<false, false, true> >::iterator]'
<source>:12:36:   required from here
/opt/compiler-explorer/gcc-11.2.0/include/c++/11.2.0/ext/new_allocator.h:162:11: error: 'Minimal::Minimal(int)' is private within this context
162 |         { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
|           ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>:19:5: note: declared private here
19 |     Minimal(int id) : id_(id) {};
|     ^~~~~~~

理解这个错误,这是由于没有在对象的范围内调用template((的分配器,因此它无法访问私有构造函数。但我该如何避开它呢?

不要将构造函数设为私有的。相反,这会让你很难从课外打电话。

例如,您可以添加private: struct PrivateTag {};,并添加PrivateTag &作为构造函数的参数。

(注意左值引用。通过值或常量引用传递标记不起作用,因为它允许任何人只传递{}。(

相关内容

最新更新