Base class has inacessible destructor

153 views Asked by At

The following code tries to define a self-similar datastructure JSON using the std containers std::vector and std::unordered_map but does not compile. It all seems to come down to std::unordered_map's hashtable deleting its destructor because it is inaccessible/private in the base class. I can't really put my fingers on why this would happen. Following my previous question any cyclic dependency regarding allocators should have been resolved and the cyclic dependencies of vectors and unordered_map's value types should be supported as of 2022.

Demo

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

/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 says:

/opt/compiler-explorer/gcc-trunk-20230415/include/c++/13.0.1/bits/functional_hash.h:84:7: note: declared private here
   84 |       ~__hash_enum();
      |

Why would it suddenly be declared private?

1

There are 1 answers

0
Benjamin Buch On

To find such errors it is best to simplify the code as long as the error still occurs. In this reduced version the problem then becomes recognizable:

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

I think what you wanted to do is std::hash<StringType> instead of std::hash<JSON<StringType, Allocator>> since the hash map needs a unique key and not a unique value.