Inline visitor implementation for C++11
Clash 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:
- Is there a better way to extract the type of the first argument of the function that using my
arg_type
template - Is there a better way of passing in the default visit implementation other than as a functor in a
template template
argument? - 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 thevisit()
implementations into separate interfaces, so I'm wondering if there is a downside to this idea? - Can I avoid storing my
visit()
implementations in astd::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;
c++ c++11 template visitor-pattern
add a comment |Â
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:
- Is there a better way to extract the type of the first argument of the function that using my
arg_type
template - Is there a better way of passing in the default visit implementation other than as a functor in a
template template
argument? - 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 thevisit()
implementations into separate interfaces, so I'm wondering if there is a downside to this idea? - Can I avoid storing my
visit()
implementations in astd::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;
c++ c++11 template visitor-pattern
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
add a comment |Â
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:
- Is there a better way to extract the type of the first argument of the function that using my
arg_type
template - Is there a better way of passing in the default visit implementation other than as a functor in a
template template
argument? - 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 thevisit()
implementations into separate interfaces, so I'm wondering if there is a downside to this idea? - Can I avoid storing my
visit()
implementations in astd::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;
c++ c++11 template visitor-pattern
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:
- Is there a better way to extract the type of the first argument of the function that using my
arg_type
template - Is there a better way of passing in the default visit implementation other than as a functor in a
template template
argument? - 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 thevisit()
implementations into separate interfaces, so I'm wondering if there is a downside to this idea? - Can I avoid storing my
visit()
implementations in astd::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;
c++ c++11 template visitor-pattern
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
add a comment |Â
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
add a comment |Â
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.
Really interesting points. I shall digest these and dig more intostd::variant
as I am not so familiar with it
â the4thamigo_uk
Jan 17 at 6:24
add a comment |Â
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.
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
add a comment |Â
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.
Really interesting points. I shall digest these and dig more intostd::variant
as I am not so familiar with it
â the4thamigo_uk
Jan 17 at 6:24
add a comment |Â
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.
Really interesting points. I shall digest these and dig more intostd::variant
as I am not so familiar with it
â the4thamigo_uk
Jan 17 at 6:24
add a comment |Â
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.
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.
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 intostd::variant
as I am not so familiar with it
â the4thamigo_uk
Jan 17 at 6:24
add a comment |Â
Really interesting points. I shall digest these and dig more intostd::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
add a comment |Â
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.
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
add a comment |Â
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.
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
add a comment |Â
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.
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.
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
add a comment |Â
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
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
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
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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