Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 7171011
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 28, 20262026-05-28T15:19:35+00:00 2026-05-28T15:19:35+00:00

I thought it would be a simple exercise to write a generic visitor base

  • 0

I thought it would be a simple exercise to write a generic visitor base class template. The goal is to be able to write

typedef visitor<some_base, some_derived1, some_derived2> my_visitor;

…and then have my_visitor be a type that is functionally equivalent to

struct my_visitor {
    virtual void visit(some_base&) {}
    virtual void visit(some_derived1&) {}
    virtual void visit(some_derived2&) {}
};

which i can inherit with actually useful derived visitor classes for that type hierarchy, which override the different visit() versions as needed. I want it to work for any number of types having any inheritance relations, and i don’t want to use any hacks that reimplement virtual functions using type_info comparisons. This is what I came up with:

#include <cstdlib>
#include <iostream>
#include <vector>


/** This is the generic part that would go in a visitor.hpp header. */
template <typename T> struct visitor_base {
    virtual void visit(T&) {};
};

template <typename... T> struct visitor : visitor_base<T>... {};


/** This is the part that is specific to a certain type hierarchy. */
struct base;
struct derived1;
struct derived2;

typedef visitor<base, derived1, derived2> my_visitor;


/** This is the type hierarchy. */
struct base {
    virtual void accept(my_visitor& v) { v.visit(*this); }
};

struct derived1 : base {
    derived1() : i(42) {}
    virtual void accept(my_visitor& v) { v.visit(*this); }
    int i;
};

struct derived2 : base {
    derived2() : f(2.79) {}
    virtual void accept(my_visitor& v) { v.visit(*this); }
    float f;
};


/** These are the algorithms. */
struct print_visitor : my_visitor {
    void visit(base&) { std::cout<<"that was a base."<<std::endl; }
    void visit(derived1& d) { std::cout<<"that was "<<d.i<<std::endl; }
    void visit(derived2& d) { std::cout<<"that was "<<d.f<<std::endl; }
};

struct randomise_visitor : my_visitor {
    void visit(derived1& d) { d.i = std::rand(); }
    void visit(derived2& d) { d.f = std::rand() / float(RAND_MAX); }
};


int main() {
    std::vector<base*> objects { new base, new derived1, new derived2,
                                 new derived2, new base };

    print_visitor p;
    randomise_visitor r;

    for (auto& o : objects) o->accept(p);
    for (auto& o : objects) o->accept(r);
    for (auto& o : objects) o->accept(p);
}

The problem is that this does not compile. GCC says

silly_visitor.cpp: In member function ‘virtual void base::accept(my_visitor&)’:
silly_visitor.cpp:24:42: error: request for member ‘visit’ is ambiguous
silly_visitor.cpp:8:16: error: candidates are: void visitor_base<T>::visit(T&) [with T = derived2]
silly_visitor.cpp:8:16: error:                 void visitor_base<T>::visit(T&) [with T = derived1]
silly_visitor.cpp:8:16: error:                 void visitor_base<T>::visit(T&) [with T = base]

Basically, the problem is that since the different visit() member functions are declared in different classes, they are not seen as candidates for overload resolution but just as ambiguous member access. The normal trick for forcing the compiler to consider inherited functions for overload resolution is to redeclare them in the derived class with ‘using’ statements, but that is not feasible in this case since it would ruin the whole generic aspect of it.

So, apparently this was not as easy as I thought. Any ideas?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-05-28T15:19:36+00:00Added an answer on May 28, 2026 at 3:19 pm

    The compiler doesn’t know which base-class’ visit function to call. See this question of mine. As such, as you correctly said, you need to make the functions available in the visitor class with using declarations. Sadly, you can’t just use using visitor_base<T>::visit...;, as that is not a valid pattern. You have to recursively inherit from one base after another and everytime bring the base-class visits into the scope of the derived class:

    template <typename T>
    struct visitor_base {
        virtual void visit(T&) {};
    };
    
    template <typename Head, typename... Tail>
    struct recursive_visitor_base
      : visitor_base<Head>
      , recursive_visitor_base<Tail...>
    {
      using visitor_base<Head>::visit;
      using recursive_visitor_base<Tail...>::visit;
    };
    
    template<class T>
    struct recursive_visitor_base<T>
      : visitor_base<T>
    {
      using visitor_base<T>::visit;
    };
    
    template <typename... T>
    struct visitor
      : recursive_visitor_base<T...>
    {
      using recursive_visitor_base<T...>::visit;
    };
    

    Live example on Ideone (I had to tweak the partial spec a bit, since GCC 4.5.1 is a bit buggy in that part. Clang compiles the code shown in this answer just fine). Output:

    that was a base.
    that was 42
    that was 2.79
    that was 2.79
    that was a base.
    =================
    that was a base.
    that was 1804289383
    that was 8.46931e+08
    that was 1.68169e+09
    that was a base.
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I am trying to do something I thought would be simple. I have a
I thought this would be simple, but its not working .. in both the
This is what I thought would be a simple select clause, however the following
I am trying to Emit what I thought would be a simple object array
I'm trying to do something which I thought would be fairly simple. Get IIS
I'm being stymied by what I thought would be the relatively simple task of
Thanks for reading this. I would have thought it would be as simple as
I thought this would be simple but obviously not! Basically, I have a date
I thought this would be simple, but searching Google didn't seem to help. I'm
I'm trying to do something I thought would be very simple: draw a hardcoded

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.