簡體   English   中英

從它自己的 static 成員 func 中嵌入一個 object 會產生“構造函數聲明私有錯誤”

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM