Inline visitor implementation for C++11

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP





.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty margin-bottom:0;







up vote
4
down vote

favorite












I've been looking at getting back into C++11 after a few years and came across the idea of implementing the 'inline' visitor pattern. The idea is that you can specify your visitor class locally in the code using lambdas, function pointers and/or std::function. Missing functions would default to a default implementation (D in the code below). I would be interested in the opinion of any C++11 gurus out there about improvements that I can make, or if there is a much better way to do this. Over time I'd like to formalize this simple idea into a much better library, so any contributions would be welcome.



My questions:



  1. Is there a better way to extract the type of the first argument of the function that using my arg_type template

  2. Is there a better way of passing in the default visit implementation other than as a functor in a template template argument?

  3. To me having the nodes reference an interface of the visitor exclusively for their type (ivisitor<mynodetype>) seems sensible, but usually the visitor pattern doesn't separate the visit() implementations into separate interfaces, so I'm wondering if there is a downside to this idea?

  4. Can I avoid storing my visit() implementations in a std::function datamember?

GitHub



#include <functional>
#inline-visitor.hpp

template<typename T>
struct arg_type :
public arg_type<decltype(&T::operator())> ;

template<typename T>
struct arg_type<void(*)(T&)> :
public arg_type<void(T&)> ;

template<typename T, typename C>
struct arg_type<void(C::*)(T&) const > :
public arg_type<void(T&)> ;

template<typename T>
struct arg_type<void(T&)>
typedef T type;
;

template<typename T>
class ivisitor
public:
virtual ~ivisitor() = default;
virtual void visit(T& node) = 0;
;

template<typename T, template<typename> class D>
class visitor : public ivisitor<T>
public:
visitor():
f_(D<T>())

void visit(T& node) override
if(f_)
f_(node);


void set(std::function<void(T&)> f)
f_ = f;

private:
std::function<void(T&)> f_;
;

template<template<typename> class D, typename ...T>
class compound_visitor : public visitor<T, D>...
public:

compound_visitor() = default;

template<typename ...F>
compound_visitor(F... f)
set(f...);

template<typename F, typename ...Fs>
void set(F f, Fs... fs)
set(f);
set(fs...);


template<typename U>
void visit(U& node)
this->visitor<U, D>::visit(node);


template<typename F>
void set(F f)
this->visitor<typename arg_type<F>::type, D>::set(f);

;

template<typename C, typename ...F>
auto make_compound_visitor(F... f) -> C
return c(f...);



Example code follows:



main.cpp



#include "inline_visitor.hpp"
#include <iostream>

template<typename T>
struct output_default
void operator()(T&)
std::cout << "default";

;

class node1
public:
void accept(ivisitor<node1>& v)
v.visit(*this);

;
class node2
public:
void accept(ivisitor<node2>& v)
v.visit(*this);

;

class node3
public:
void accept(ivisitor<node3>& v)
v.visit(*this);

;

class node4
public:
void accept(ivisitor<node4>& v)
v.visit(*this);

;

int main(int argc, char** argv)
typedef compound_visitor<output_default, node1, node2, node3, node4> concrete_visitor;
auto v = make_compound_visitor<concrete_visitor>(
(node1& node) -> void std::cout << "n1";,
std::function<void(node2&)>((node2& node) -> void std::cout << "n2";),
+(node3& node) -> void std::cout << "n3";
);

node1 n1;
node2 n2;
node3 n3;
node4 n4;

n1.accept(v);
n2.accept(v);
n3.accept(v);
n4.accept(v);

return 0;







share|improve this question





















  • I guess one response to Q3 is that normally the nodes would be stored in some homogenous list and processed iteratively, requiring them to share a common interface.
    – the4thamigo_uk
    Jan 17 at 6:18
















up vote
4
down vote

favorite












I've been looking at getting back into C++11 after a few years and came across the idea of implementing the 'inline' visitor pattern. The idea is that you can specify your visitor class locally in the code using lambdas, function pointers and/or std::function. Missing functions would default to a default implementation (D in the code below). I would be interested in the opinion of any C++11 gurus out there about improvements that I can make, or if there is a much better way to do this. Over time I'd like to formalize this simple idea into a much better library, so any contributions would be welcome.



My questions:



  1. Is there a better way to extract the type of the first argument of the function that using my arg_type template

  2. Is there a better way of passing in the default visit implementation other than as a functor in a template template argument?

  3. To me having the nodes reference an interface of the visitor exclusively for their type (ivisitor<mynodetype>) seems sensible, but usually the visitor pattern doesn't separate the visit() implementations into separate interfaces, so I'm wondering if there is a downside to this idea?

  4. Can I avoid storing my visit() implementations in a std::function datamember?

GitHub



#include <functional>
#inline-visitor.hpp

template<typename T>
struct arg_type :
public arg_type<decltype(&T::operator())> ;

template<typename T>
struct arg_type<void(*)(T&)> :
public arg_type<void(T&)> ;

template<typename T, typename C>
struct arg_type<void(C::*)(T&) const > :
public arg_type<void(T&)> ;

template<typename T>
struct arg_type<void(T&)>
typedef T type;
;

template<typename T>
class ivisitor
public:
virtual ~ivisitor() = default;
virtual void visit(T& node) = 0;
;

template<typename T, template<typename> class D>
class visitor : public ivisitor<T>
public:
visitor():
f_(D<T>())

void visit(T& node) override
if(f_)
f_(node);


void set(std::function<void(T&)> f)
f_ = f;

private:
std::function<void(T&)> f_;
;

template<template<typename> class D, typename ...T>
class compound_visitor : public visitor<T, D>...
public:

compound_visitor() = default;

template<typename ...F>
compound_visitor(F... f)
set(f...);

template<typename F, typename ...Fs>
void set(F f, Fs... fs)
set(f);
set(fs...);


template<typename U>
void visit(U& node)
this->visitor<U, D>::visit(node);


template<typename F>
void set(F f)
this->visitor<typename arg_type<F>::type, D>::set(f);

;

template<typename C, typename ...F>
auto make_compound_visitor(F... f) -> C
return c(f...);



Example code follows:



main.cpp



#include "inline_visitor.hpp"
#include <iostream>

template<typename T>
struct output_default
void operator()(T&)
std::cout << "default";

;

class node1
public:
void accept(ivisitor<node1>& v)
v.visit(*this);

;
class node2
public:
void accept(ivisitor<node2>& v)
v.visit(*this);

;

class node3
public:
void accept(ivisitor<node3>& v)
v.visit(*this);

;

class node4
public:
void accept(ivisitor<node4>& v)
v.visit(*this);

;

int main(int argc, char** argv)
typedef compound_visitor<output_default, node1, node2, node3, node4> concrete_visitor;
auto v = make_compound_visitor<concrete_visitor>(
(node1& node) -> void std::cout << "n1";,
std::function<void(node2&)>((node2& node) -> void std::cout << "n2";),
+(node3& node) -> void std::cout << "n3";
);

node1 n1;
node2 n2;
node3 n3;
node4 n4;

n1.accept(v);
n2.accept(v);
n3.accept(v);
n4.accept(v);

return 0;







share|improve this question





















  • I guess one response to Q3 is that normally the nodes would be stored in some homogenous list and processed iteratively, requiring them to share a common interface.
    – the4thamigo_uk
    Jan 17 at 6:18












up vote
4
down vote

favorite









up vote
4
down vote

favorite











I've been looking at getting back into C++11 after a few years and came across the idea of implementing the 'inline' visitor pattern. The idea is that you can specify your visitor class locally in the code using lambdas, function pointers and/or std::function. Missing functions would default to a default implementation (D in the code below). I would be interested in the opinion of any C++11 gurus out there about improvements that I can make, or if there is a much better way to do this. Over time I'd like to formalize this simple idea into a much better library, so any contributions would be welcome.



My questions:



  1. Is there a better way to extract the type of the first argument of the function that using my arg_type template

  2. Is there a better way of passing in the default visit implementation other than as a functor in a template template argument?

  3. To me having the nodes reference an interface of the visitor exclusively for their type (ivisitor<mynodetype>) seems sensible, but usually the visitor pattern doesn't separate the visit() implementations into separate interfaces, so I'm wondering if there is a downside to this idea?

  4. Can I avoid storing my visit() implementations in a std::function datamember?

GitHub



#include <functional>
#inline-visitor.hpp

template<typename T>
struct arg_type :
public arg_type<decltype(&T::operator())> ;

template<typename T>
struct arg_type<void(*)(T&)> :
public arg_type<void(T&)> ;

template<typename T, typename C>
struct arg_type<void(C::*)(T&) const > :
public arg_type<void(T&)> ;

template<typename T>
struct arg_type<void(T&)>
typedef T type;
;

template<typename T>
class ivisitor
public:
virtual ~ivisitor() = default;
virtual void visit(T& node) = 0;
;

template<typename T, template<typename> class D>
class visitor : public ivisitor<T>
public:
visitor():
f_(D<T>())

void visit(T& node) override
if(f_)
f_(node);


void set(std::function<void(T&)> f)
f_ = f;

private:
std::function<void(T&)> f_;
;

template<template<typename> class D, typename ...T>
class compound_visitor : public visitor<T, D>...
public:

compound_visitor() = default;

template<typename ...F>
compound_visitor(F... f)
set(f...);

template<typename F, typename ...Fs>
void set(F f, Fs... fs)
set(f);
set(fs...);


template<typename U>
void visit(U& node)
this->visitor<U, D>::visit(node);


template<typename F>
void set(F f)
this->visitor<typename arg_type<F>::type, D>::set(f);

;

template<typename C, typename ...F>
auto make_compound_visitor(F... f) -> C
return c(f...);



Example code follows:



main.cpp



#include "inline_visitor.hpp"
#include <iostream>

template<typename T>
struct output_default
void operator()(T&)
std::cout << "default";

;

class node1
public:
void accept(ivisitor<node1>& v)
v.visit(*this);

;
class node2
public:
void accept(ivisitor<node2>& v)
v.visit(*this);

;

class node3
public:
void accept(ivisitor<node3>& v)
v.visit(*this);

;

class node4
public:
void accept(ivisitor<node4>& v)
v.visit(*this);

;

int main(int argc, char** argv)
typedef compound_visitor<output_default, node1, node2, node3, node4> concrete_visitor;
auto v = make_compound_visitor<concrete_visitor>(
(node1& node) -> void std::cout << "n1";,
std::function<void(node2&)>((node2& node) -> void std::cout << "n2";),
+(node3& node) -> void std::cout << "n3";
);

node1 n1;
node2 n2;
node3 n3;
node4 n4;

n1.accept(v);
n2.accept(v);
n3.accept(v);
n4.accept(v);

return 0;







share|improve this question













I've been looking at getting back into C++11 after a few years and came across the idea of implementing the 'inline' visitor pattern. The idea is that you can specify your visitor class locally in the code using lambdas, function pointers and/or std::function. Missing functions would default to a default implementation (D in the code below). I would be interested in the opinion of any C++11 gurus out there about improvements that I can make, or if there is a much better way to do this. Over time I'd like to formalize this simple idea into a much better library, so any contributions would be welcome.



My questions:



  1. Is there a better way to extract the type of the first argument of the function that using my arg_type template

  2. Is there a better way of passing in the default visit implementation other than as a functor in a template template argument?

  3. To me having the nodes reference an interface of the visitor exclusively for their type (ivisitor<mynodetype>) seems sensible, but usually the visitor pattern doesn't separate the visit() implementations into separate interfaces, so I'm wondering if there is a downside to this idea?

  4. Can I avoid storing my visit() implementations in a std::function datamember?

GitHub



#include <functional>
#inline-visitor.hpp

template<typename T>
struct arg_type :
public arg_type<decltype(&T::operator())> ;

template<typename T>
struct arg_type<void(*)(T&)> :
public arg_type<void(T&)> ;

template<typename T, typename C>
struct arg_type<void(C::*)(T&) const > :
public arg_type<void(T&)> ;

template<typename T>
struct arg_type<void(T&)>
typedef T type;
;

template<typename T>
class ivisitor
public:
virtual ~ivisitor() = default;
virtual void visit(T& node) = 0;
;

template<typename T, template<typename> class D>
class visitor : public ivisitor<T>
public:
visitor():
f_(D<T>())

void visit(T& node) override
if(f_)
f_(node);


void set(std::function<void(T&)> f)
f_ = f;

private:
std::function<void(T&)> f_;
;

template<template<typename> class D, typename ...T>
class compound_visitor : public visitor<T, D>...
public:

compound_visitor() = default;

template<typename ...F>
compound_visitor(F... f)
set(f...);

template<typename F, typename ...Fs>
void set(F f, Fs... fs)
set(f);
set(fs...);


template<typename U>
void visit(U& node)
this->visitor<U, D>::visit(node);


template<typename F>
void set(F f)
this->visitor<typename arg_type<F>::type, D>::set(f);

;

template<typename C, typename ...F>
auto make_compound_visitor(F... f) -> C
return c(f...);



Example code follows:



main.cpp



#include "inline_visitor.hpp"
#include <iostream>

template<typename T>
struct output_default
void operator()(T&)
std::cout << "default";

;

class node1
public:
void accept(ivisitor<node1>& v)
v.visit(*this);

;
class node2
public:
void accept(ivisitor<node2>& v)
v.visit(*this);

;

class node3
public:
void accept(ivisitor<node3>& v)
v.visit(*this);

;

class node4
public:
void accept(ivisitor<node4>& v)
v.visit(*this);

;

int main(int argc, char** argv)
typedef compound_visitor<output_default, node1, node2, node3, node4> concrete_visitor;
auto v = make_compound_visitor<concrete_visitor>(
(node1& node) -> void std::cout << "n1";,
std::function<void(node2&)>((node2& node) -> void std::cout << "n2";),
+(node3& node) -> void std::cout << "n3";
);

node1 n1;
node2 n2;
node3 n3;
node4 n4;

n1.accept(v);
n2.accept(v);
n3.accept(v);
n4.accept(v);

return 0;









share|improve this question












share|improve this question




share|improve this question








edited Jan 15 at 23:53









Jamal♦

30.1k11114225




30.1k11114225









asked Jan 15 at 22:25









the4thamigo_uk

1213




1213











  • I guess one response to Q3 is that normally the nodes would be stored in some homogenous list and processed iteratively, requiring them to share a common interface.
    – the4thamigo_uk
    Jan 17 at 6:18
















  • I guess one response to Q3 is that normally the nodes would be stored in some homogenous list and processed iteratively, requiring them to share a common interface.
    – the4thamigo_uk
    Jan 17 at 6:18















I guess one response to Q3 is that normally the nodes would be stored in some homogenous list and processed iteratively, requiring them to share a common interface.
– the4thamigo_uk
Jan 17 at 6:18




I guess one response to Q3 is that normally the nodes would be stored in some homogenous list and processed iteratively, requiring them to share a common interface.
– the4thamigo_uk
Jan 17 at 6:18










2 Answers
2






active

oldest

votes

















up vote
1
down vote













Inheritance



I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.



Use cases



Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.



Too much runtime



If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.



Static way



Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.



template<class... Ts> struct overloaded : Ts... using Ts::operator()...; ;
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;


This requires C++17, but not hard to emulate using C++14, using make_overloaded.



Now, the usage:



 std::visit(overloaded 
(auto arg) std::cout << arg << ' '; ,
(double arg) std::cout << std::fixed << arg << ' '; ,
(const std::string& arg) std::cout << std::quoted(arg) << ' '; ,
, v); // v is std::variant


As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.






share|improve this answer























  • Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
    – the4thamigo_uk
    Jan 17 at 6:24

















up vote
0
down vote













looks interesting! I'd be interested in the details. Have you seen this?



https://accu.org/index.php/articles/2021




Missing functions would default to a default implementation




If you have a closed set of types, I wouldn't recommend missing/default implementations for visited types. One benefit of visiting is that if you add a new type you are forced to write missing implementations for all the visitors without overlooking any.






share|improve this answer





















  • Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
    – the4thamigo_uk
    Jan 24 at 12:07










Your Answer




StackExchange.ifUsing("editor", function ()
return StackExchange.using("mathjaxEditing", function ()
StackExchange.MarkdownEditor.creationCallbacks.add(function (editor, postfix)
StackExchange.mathjaxEditing.prepareWmdForMathJax(editor, postfix, [["\$", "\$"]]);
);
);
, "mathjax-editing");

StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");

StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "196"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);

StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);

else
createEditor();

);

function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
convertImagesToLinks: false,
noModals: false,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);



);








 

draft saved


draft discarded


















StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185169%2finline-visitor-implementation-for-c11%23new-answer', 'question_page');

);

Post as a guest






























2 Answers
2






active

oldest

votes








2 Answers
2






active

oldest

votes









active

oldest

votes






active

oldest

votes








up vote
1
down vote













Inheritance



I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.



Use cases



Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.



Too much runtime



If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.



Static way



Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.



template<class... Ts> struct overloaded : Ts... using Ts::operator()...; ;
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;


This requires C++17, but not hard to emulate using C++14, using make_overloaded.



Now, the usage:



 std::visit(overloaded 
(auto arg) std::cout << arg << ' '; ,
(double arg) std::cout << std::fixed << arg << ' '; ,
(const std::string& arg) std::cout << std::quoted(arg) << ' '; ,
, v); // v is std::variant


As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.






share|improve this answer























  • Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
    – the4thamigo_uk
    Jan 17 at 6:24














up vote
1
down vote













Inheritance



I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.



Use cases



Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.



Too much runtime



If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.



Static way



Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.



template<class... Ts> struct overloaded : Ts... using Ts::operator()...; ;
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;


This requires C++17, but not hard to emulate using C++14, using make_overloaded.



Now, the usage:



 std::visit(overloaded 
(auto arg) std::cout << arg << ' '; ,
(double arg) std::cout << std::fixed << arg << ' '; ,
(const std::string& arg) std::cout << std::quoted(arg) << ' '; ,
, v); // v is std::variant


As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.






share|improve this answer























  • Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
    – the4thamigo_uk
    Jan 17 at 6:24












up vote
1
down vote










up vote
1
down vote









Inheritance



I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.



Use cases



Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.



Too much runtime



If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.



Static way



Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.



template<class... Ts> struct overloaded : Ts... using Ts::operator()...; ;
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;


This requires C++17, but not hard to emulate using C++14, using make_overloaded.



Now, the usage:



 std::visit(overloaded 
(auto arg) std::cout << arg << ' '; ,
(double arg) std::cout << std::fixed << arg << ' '; ,
(const std::string& arg) std::cout << std::quoted(arg) << ' '; ,
, v); // v is std::variant


As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.






share|improve this answer















Inheritance



I believe that inheritance based OOP is painful to use in C++ compared to languages like java. In my opinion, static polymorphism is better. Runtime polymorphism is hard to do because C++ has manual memory (and ownership semantics in general) and local variables are strongly typed.



Use cases



Personally I can't see a use case for visitor. They might be useful in conjunction with std::variant, but otherwise I fail to see it being useful.



Too much runtime



If a function is virtual, there is no need to store it in std::function. Too many indirections, and the last one has type erasure, which is heavier mechanism than runtime polymorphism.



Static way



Visitors are usually used to get double dispatch. Templates provide N way dispatch, e.g. the type will keep propagating as long as the call chain is all templated. Lets look at this interesting example from std::visit documentation page.



template<class... Ts> struct overloaded : Ts... using Ts::operator()...; ;
template<class... Ts> overloaded(Ts...) -> overloaded<Ts...>;


This requires C++17, but not hard to emulate using C++14, using make_overloaded.



Now, the usage:



 std::visit(overloaded 
(auto arg) std::cout << arg << ' '; ,
(double arg) std::cout << std::fixed << arg << ' '; ,
(const std::string& arg) std::cout << std::quoted(arg) << ' '; ,
, v); // v is std::variant


As you can see, types are actually inferred, so the need for std::function just goes away. Usually, templates are good way to go unless it is some highly dynamic environment like GUI, where I would pick Qt framework or, for a language, python, or any other duck typed language.







share|improve this answer















share|improve this answer



share|improve this answer








edited Jan 16 at 21:28


























answered Jan 16 at 21:21









Incomputable

6,19221246




6,19221246











  • Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
    – the4thamigo_uk
    Jan 17 at 6:24
















  • Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
    – the4thamigo_uk
    Jan 17 at 6:24















Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
– the4thamigo_uk
Jan 17 at 6:24




Really interesting points. I shall digest these and dig more into std::variant as I am not so familiar with it
– the4thamigo_uk
Jan 17 at 6:24












up vote
0
down vote













looks interesting! I'd be interested in the details. Have you seen this?



https://accu.org/index.php/articles/2021




Missing functions would default to a default implementation




If you have a closed set of types, I wouldn't recommend missing/default implementations for visited types. One benefit of visiting is that if you add a new type you are forced to write missing implementations for all the visitors without overlooking any.






share|improve this answer





















  • Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
    – the4thamigo_uk
    Jan 24 at 12:07














up vote
0
down vote













looks interesting! I'd be interested in the details. Have you seen this?



https://accu.org/index.php/articles/2021




Missing functions would default to a default implementation




If you have a closed set of types, I wouldn't recommend missing/default implementations for visited types. One benefit of visiting is that if you add a new type you are forced to write missing implementations for all the visitors without overlooking any.






share|improve this answer





















  • Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
    – the4thamigo_uk
    Jan 24 at 12:07












up vote
0
down vote










up vote
0
down vote









looks interesting! I'd be interested in the details. Have you seen this?



https://accu.org/index.php/articles/2021




Missing functions would default to a default implementation




If you have a closed set of types, I wouldn't recommend missing/default implementations for visited types. One benefit of visiting is that if you add a new type you are forced to write missing implementations for all the visitors without overlooking any.






share|improve this answer













looks interesting! I'd be interested in the details. Have you seen this?



https://accu.org/index.php/articles/2021




Missing functions would default to a default implementation




If you have a closed set of types, I wouldn't recommend missing/default implementations for visited types. One benefit of visiting is that if you add a new type you are forced to write missing implementations for all the visitors without overlooking any.







share|improve this answer













share|improve this answer



share|improve this answer











answered Jan 24 at 9:38









Dresden

1




1











  • Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
    – the4thamigo_uk
    Jan 24 at 12:07
















  • Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
    – the4thamigo_uk
    Jan 24 at 12:07















Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
– the4thamigo_uk
Jan 24 at 12:07




Im afraid that is all I have so far github.com/the4thamigo-uk/inline-visitor. P.S. I did see that article at some point I think...
– the4thamigo_uk
Jan 24 at 12:07












 

draft saved


draft discarded


























 


draft saved


draft discarded














StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fcodereview.stackexchange.com%2fquestions%2f185169%2finline-visitor-implementation-for-c11%23new-answer', 'question_page');

);

Post as a guest













































































Popular posts from this blog

Chat program with C++ and SFML

Function to Return a JSON Like Objects Using VBA Collections and Arrays

Will my employers contract hold up in court?