Search code examples
c++visual-c++c++17variadic-templatesusing-declaration

Variadic base class using declaration fails to compile in MSVC


I'm trying to implement a variadic visitor class.

template<typename T>
class VisitorBaseFor {
protected:
   virtual ~VisitorBaseFor() = default;

public:
   virtual void visit(T &t) = 0;
};

template<typename... Ts>
class VisitorBase : public VisitorBaseFor<Ts>... {
public:
    using VisitorBaseFor<Ts>::visit...;
};

I know from that overload trick that variadic using declarations should be possible, but MSVC does not compile my code saying I need to expand Ts while both GCC and Clang compile my code without errors, see here.

What am I missing? Is this a MSVC bug or just not (yet) supported? If it is, is there a way to work around this?

Apart from that I have tried to remove the using declaration but then the calls to visit become ambiguous for some reason, even though all classes in Ts are not convertible to each other. This is being diagnosed correctly by MSVC, but why are they even used in overload resolution then?

Update: This is a known bug since at least Sep 03, 2018. See here and here.


Solution

  • Code is indeed correct and so bug of msvc.

    Workaround is to manually do the recursion:

    template<typename T>
    class VisitorBaseImpl {
    protected:
        virtual ~VisitorBaseImpl() = default;
    
    public:
        virtual void visit(T &t) = 0;
    };
    
    template<typename... Ts> class VisitorBase;
    
    template<typename T>
    class VisitorBase<T> : public VisitorBaseImpl<T>
    {
    };
    
    template<typename T, typename... Ts>
    class VisitorBase<T, Ts...> : public VisitorBase<T>, public VisitorBase<Ts...>
    {
    public:
        using VisitorBase<T>::visit;
        using VisitorBase<Ts...>::visit;
    };
    

    Demo