[英]Emplacing an object from its own static member func yields "constructor declared private error"
在下面的代碼片段中,我嘗試從 object 的 static 成員 function 中實例化對象(工廠方法)。 我正在通過 ::emplace() 將新創建的 object 放入 unordered_map 中,但這失敗了,因為我想讓構造函數私有(在真實上下文中,另一個 static 成員 function 調用 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) {};
| ^~~~~~~
我理解這個錯誤是由於 emplace() 的分配器沒有在 object 的 scope 中被調用,因此它無法訪問私有構造函數。 但是我該如何解決呢?
不要將構造函數設為私有。 相反,很難從 class 以外的地方撥打電話。
例如,您可以添加private: struct PrivateTag {};
, 並添加PrivateTag &
作為構造函數的參數。
(注意左值引用。通過值或 const 引用傳遞標簽是行不通的,因為它允許任何人只傳遞{}
。)
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.