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 1056771
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: May 16, 20262026-05-16T17:45:51+00:00 2026-05-16T17:45:51+00:00

As a personal exercise, I want to implement the visitor pattern using shared_ptr. I

  • 0

As a personal exercise, I want to implement the visitor pattern using shared_ptr. I am familiar with Robert Martin’s acyclic visitor paper but find the intrusive nature of the virtual accept() and necessary creation of an {X}Visitor class for each {X} class unpleasant. I like the boost::static_visitor class as it encapsulates all the logic locally without the necessity of {X}::accept() and {X}Visitor.

What I am looking for is a hint (as I said, I’m doing this as an exercise) of how to create the template function function rip I mention below. I think it should be of the form:

template <typename U, typename T1, typename T2, ...>
boost::variant<T1, T2, ...> rip(U& p, boost::static_visitor<T1, T2, ...> sv)
{
    if (T1 t1 = dynamic_cast<T1>(p)) return boost::variant<T1, ...>(t1);
    ... and so on, splitting static_visitor
    return 0;  // or throw an exception
}

Any hints or pointers to tutorials doing similar things would be appreciated. Thanks.

#include <algorithm>
#include <cstdlib>
#include <iostream>
#include <memory>
#include <boost/bind.hpp>
#include <boost/variant.hpp>


struct Base {};
struct A : Base {};
struct B : Base {};
struct C : Base {};

typedef std::shared_ptr<Base> base_ptr;
typedef boost::variant<A*,B*,C*> base_variant;
struct variant_visitor : public boost::static_visitor<void> {
    void operator()(A*, base_ptr) const {std::cout << "A*\n";}
    void operator()(B*, base_ptr) const {std::cout << "B*\n";}
    void operator()(C*, base_ptr) const {std::cout << "C*\n";}
};


int main(int, char**)
{
    // This works, of course.
    base_ptr b(new A());
    base_variant v(new A());
    boost::apply_visitor(boost::bind(variant_visitor(), _1, b), v);

    // How could we use a shared_ptr with a variant?  I almost see
    // the template magic, a function to iterate over the template
    // types from the variant_visitor and return an "any<...>".
    // base_variant rip(base_ptr&, variant_visitor) {...}
    // boost::apply_visitor(boost::bind(variant_visitor(), _1, b), rip(b, variant_visitor()));

    return EXIT_SUCCESS;
}
  • 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-16T17:45:52+00:00Added an answer on May 16, 2026 at 5:45 pm

    I may be misunderstanding the question, but if you want to use the same variant_visitor for a variant containing shared pointers instead of plain pointers, perhaps this can be achieved with another visitor that obtains the pointer from the shared_ptr and passes it on to the other visitor.

    #include <algorithm>
    #include <cstdlib>
    #include <iostream>
    #include <boost/shared_ptr.hpp>
    #include <boost/bind.hpp>
    #include <boost/variant.hpp>
    
    
    struct Base {};
    struct A : Base {};
    struct B : Base {};
    struct C : Base {};
    
    typedef boost::shared_ptr<Base> base_ptr;
    typedef boost::variant<boost::shared_ptr<A>,boost::shared_ptr<B>,boost::shared_ptr<C> > base_variant;
    
    template <class Visitor>
    struct visit_shared_ptr_get: public boost::static_visitor<typename Visitor::result_type>
    {
        //for unary visitors
        template <class FirstArg>
        typename Visitor::result_type operator()(FirstArg& first) const
        {
            return Visitor()(first.get());
        }  
    
        //for binary visitors, only the first argument is "ripped"
        template <class FirstArg, class SecondArg>
        typename Visitor::result_type operator()(FirstArg& first, SecondArg& second) const
        {
            return Visitor()(first.get(), second);
        }  
    };
    
    struct variant_visitor : public boost::static_visitor<void> {
        void operator()(A*, base_ptr) const {std::cout << "A*\n";}
        void operator()(B*, base_ptr) const {std::cout << "B*\n";}
        void operator()(C*, base_ptr) const {std::cout << "C*\n";}
    };
    
    
    int main(int, char**)
    {
        // This works, of course.
        base_ptr b(new A());
        base_variant v(boost::shared_ptr<A>(new A()));
        boost::apply_visitor(boost::bind(visit_shared_ptr_get<variant_visitor>(), _1, b), v);
        return EXIT_SUCCESS;
    }
    

    Edit: a downcaster that you seem to be envisioning.

    #include <stdexcept>
    #include <boost/type_traits.hpp>
    #include <boost/utility/enable_if.hpp>
    #include <boost/shared_ptr.hpp>
    #include <boost/variant.hpp>
    #include <boost/variant/variant_fwd.hpp>
    #include <boost/preprocessor/repetition.hpp>
    
    //dynamic_cast will only compile if the target type is a pointer
    template <class Derived, class Base, class Variant>
    typename boost::enable_if<boost::is_pointer<Derived>, bool>::type cast_if_pointer( Base* b, Variant& variant)
    {
        if (Derived p = dynamic_cast<Derived>(b)) { variant = p; return true; }
        return false;
    }
    
    //weeds out boost's unused template parameters and other non-pointers
    template <class Derived, class Base, class Variant>
    typename boost::disable_if<boost::is_pointer<Derived>, bool>::type cast_if_pointer( Base*, Variant& )
    {
        return false;
    }
    
    template <class P, BOOST_VARIANT_ENUM_PARAMS(class T)>
    void rip(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)>& variant, const boost::shared_ptr<P>& smart_ptr)
    {
    #define ATTEMPT_CAST(z, n, type) if (cast_if_pointer<T ## n >(smart_ptr.get(), variant)) return;
        BOOST_PP_REPEAT(BOOST_VARIANT_LIMIT_TYPES, ATTEMPT_CAST, T)
    #undef ATTEMPT_CAST
        throw std::bad_cast();
    }
    
    struct Base 
    {
        virtual ~Base() {}
    };
    
    struct A : Base {};
    struct B : Base {};
    struct C : Base {};
    
    
    typedef boost::shared_ptr<Base> base_ptr;
    typedef boost::variant<A*,B*,C*> base_variant;
    
    
    int main(int, char**)
    {
        base_ptr b(new A());
        base_variant v;
        rip(v, b);
    
        return EXIT_SUCCESS;
    }
    
    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

I'm trying to implement some functionality of BigInteger s as a personal programming exercise.
I'm going to implement a (simple) downloader application in Java as a personal exercise.
As an exercise for my personal enlightenment, I implement vector math with expression templates.
Just for my personal wiki, I want to draw a diagram that shows how
As a personal project, I'm making an AJAX chatroom application using XML as a
As an exercise with accessibility and a personal challenge to myself I decided that
For my personal development, I want to learn web application development on the LAMP
I was doing this as a personal exercise and wanted to make sure I
For a personal research/fun project I am using the Python urllib2() function. However, when
I'm using a personal font on a web app that renders perfectly well in

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.