c++templatesconstructorbase-classusing-directives

Avoid template mess when importing base class constructors of heavily templated base class


This is just short inquiery if it is at all possible to somehow import base class constructors without all the template bloat. Consider this example where I'm inheriting from a templated std::variant:

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>, Allocator>,
                        std::vector<JSON<StringType, Allocator>, Allocator>, 
                        bool,
                        double,
                        StringType>
{
public:

    using std::variant<std::monostate,
                        std::unordered_map<StringType, JSON<StringType, Allocator>, std::hash<JSON<StringType, Allocator>>, std::equal_to<StringType>, Allocator>,
                        std::vector<JSON<StringType, Allocator>, Allocator>, 
                        bool,
                        double,
                        StringType>::variant;
};

You can see that there's quite a bit of bloat which makes it rather unreadable and error prone. Can this be avoided? The reason I'm asking is because I think I once heard that you can somehow skip template parameters within a templated class as the compiler can imply what you meant.

Clarification:

Essentially I'm just looking for a way to not writing the same template mess twice. I have tried using variant::variant which doesn't work. But there might be other ways around this and any hints are greatly appreciated!


Solution

  • The injected class name from the base class won't be found by unqualified lookup because the base class is a template that depends on template parameters of the derived class. Let's qualify that name:

    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>, Allocator>,
                            std::vector<JSON<StringType, Allocator>, Allocator>, 
                            bool,
                            double,
                            StringType>
    {
    private:
        using MyBase = typename JSON::variant;
    
    public:
        using MyBase::MyBase;
    };
    

    Demo