以下代码尝试使用 std 容器
std::vector
和 std::unordered_map
定义自相似数据结构 JSON,但未编译。这一切似乎都归结为 std::unordered_map
的哈希表删除了它的析构函数,因为它在基类中不可访问/私有。我真的无法理解为什么会发生这种情况。在我之前的问题之后,任何关于分配器的循环依赖都应该得到解决,向量的循环依赖和unordered_map的值类型应该在2022年得到支持。
#include <variant>
#include <unordered_map>
#include <vector>
#include <string>
#include <string_view>
#include <concepts>
#include <memory> // allocator
#include <memory_resource>
#include <cstddef> // std::size_t
template <typename StringType = std::string, typename Allocator = std::allocator<void>>
class JSON;
template <typename StringType, typename Allocator>
class JSON: public std::variant<std::monostate,
std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>,
typename std::allocator_traits<Allocator>::template rebind_alloc<std::pair<const StringType, JSON<StringType, Allocator>>>
>,
std::vector<JSON<StringType, Allocator>,
typename std::allocator_traits<Allocator>::template rebind_alloc<JSON<StringType, Allocator>>
>,
bool,
double,
StringType>
{
public:
using JSON::variant::variant;
};
int main() {
JSON json;
}
clang trunk 说:
/opt/compiler-explorer/gcc-snapshot/lib/gcc/x86_64-linux-gnu/13.0.1/../../../../include/c++/13.0.1/bits/functional_hash.h:102:19: note: destructor of 'hash<JSON<>>' is implicitly deleted because base class '__hash_enum<JSON<basic_string<char, char_traits<char>, allocator<char>>, allocator<void>>>' has an inaccessible destructor
struct hash : __hash_enum<_Tp>
gcc trunk 说:
/opt/compiler-explorer/gcc-trunk-20230415/include/c++/13.0.1/bits/functional_hash.h:84:7: note: declared private here
84 | ~__hash_enum();
|
为什么会突然宣布私有?
要找到这样的错误,只要错误仍然存在,最好简化代码。在这个简化版本中,问题变得可识别:
#include <string>
#include <unordered_map>
#include <variant>
template <
typename StringType = std::string,
typename Allocator = StringType::allocator_type>
struct JSON: std::variant<std::monostate,
std::unordered_map<
StringType,
JSON<StringType, Allocator>,
std::hash<
JSON<StringType, Allocator> // this is not hashable
>
>>
{
using JSON::variant::variant;
};
int main() {
JSON json;
}
我认为你想要做的是
std::hash<StringType>
而不是 std::hash<JSON<StringType, Allocator>>
因为哈希映射需要一个唯一的键而不是一个唯一的值。