基类具有不可访问的析构函数

Base class has inacessible destructor

提问人:glades 提问时间:4/15/2023 最后编辑:Benjamin Buchglades 更新时间:4/16/2023 访问量:115

问:

以下代码尝试使用 std 容器定义自相似数据结构 JSON,但未编译。这一切似乎都归结为 的哈希表删除了它的析构函数,因为它在基类中是不可访问/私有的。我真的无法解释为什么会发生这种情况。根据我之前的问题,自 2022 年起,应该已经解决了任何关于分配器的循环依赖关系,并且应该支持向量和 unordered_map 值类型的循环依赖关系。std::vectorstd::unordered_mapstd::unordered_map

演示

#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();
      |

为什么会突然被宣布为私有?

C++ 析构函数 分配器 基类 私有方法

评论

2赞 StoryTeller - Unslander Monica 4/15/2023
您正在将字符串映射到 json,哈希值应为字符串。它应该始终用于密钥类型。
0赞 gerum 4/15/2023
错误来自于您尝试将 std::hash 用于没有哈希实现的类型。
0赞 glades 4/15/2023
@StoryTeller-Unslander莫妮卡:这是有道理的。我什至没有在这个模板中看到这一点,一团糟哈哈。谢谢
0赞 Red.Wave 4/16/2023
现在,模板参数列表中需要一个哈希类。作为玩具的好运动,但你为什么不满足于?!你打算打败它吗?boost::json
0赞 glades 4/16/2023
@Red.Wave:不,但我需要一个我还没有找到的功能。我现在需要解析一半的 json,其余的稍后再解析。这将是一个基于协程的 json 解析器。

答:

2赞 Benjamin Buch 4/15/2023 #1

要查找此类错误,最好在错误仍然存在时简化代码。在这个简化版本中,问题变得可识别:

#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>>