How to specially treat the beginning of a type list?

P

PengYu.UT

Hi,

The line with the comment "// redundant" is redundant in the sense
that is never used in the main program. However, removing that line
will invalidate the program. I'm wondering if there is any way to
intelligently remove that line while still leaving the program
compilable.

Thanks,
Peng

#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>

class base {
public :
virtual ~base() {}
virtual void accept(base& b) = 0 ;
void visit() { } // redundant
};

template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
using Base::visit;
};

class A;
class B;

typedef boost::mpl::vector<A, B> AB;

typedef boost::mpl::fold<AB, base,
visitor said:
::type v;

class A : public v {
public :
void visit(A&) {
std::cout << "A-A" << std::endl;
}
void visit(B&) {
std::cout << "A-B" << std::endl;
}
void accept(base& b) {
static_cast<v&>(b).visit(*this);
}
};

class B : public v {
public :
void visit(A&) {
std::cout << "B-A" << std::endl;
}
void visit(B&) {
std::cout << "B-B" << std::endl;
}
void accept(base& b) {
static_cast<v&>(b).visit(*this);
}
};

int main(){
A a;
B b;
base& x1 = a ;
base& x2 = b ;

x1.accept(x1); // A-A
x2.accept(x1); // A-B
x1.accept(x2); // B-A
x2.accept(x2); // B-B

return EXIT_SUCCESS;
}
 
J

Jim Langston

Hi,

The line with the comment "// redundant" is redundant in the sense
that is never used in the main program. However, removing that line
will invalidate the program. I'm wondering if there is any way to
intelligently remove that line while still leaving the program
compilable.

Thanks,
Peng

#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>

class base {
public :
virtual ~base() {}
virtual void accept(base& b) = 0 ;
void visit() { } // redundant
};

template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
using Base::visit;
};

class A;
class B;

typedef boost::mpl::vector<A, B> AB;

typedef boost::mpl::fold<AB, base,


class A : public v {
public :
void visit(A&) {
std::cout << "A-A" << std::endl;
}
void visit(B&) {
std::cout << "A-B" << std::endl;
}
void accept(base& b) {
static_cast<v&>(b).visit(*this);
}
};

class B : public v {
public :
void visit(A&) {
std::cout << "B-A" << std::endl;
}
void visit(B&) {
std::cout << "B-B" << std::endl;
}
void accept(base& b) {
static_cast<v&>(b).visit(*this);
}
};

int main(){
A a;
B b;
base& x1 = a ;
base& x2 = b ;

x1.accept(x1); // A-A
x2.accept(x1); // A-B
x1.accept(x2); // B-A
x2.accept(x2); // B-B

return EXIT_SUCCESS;
}

You forgot to mark which line was redundant. Which line is it?
 
T

Thomas J. Gritzan

Jim said:
The line with the comment "// redundant" is redundant in the sense
that is never used in the main program. However, removing that line
will invalidate the program. I'm wondering if there is any way to
intelligently remove that line while still leaving the program
compilable. [...]
class base {
public :
virtual ~base() {}
virtual void accept(base& b) = 0 ;
void visit() { } // redundant

^^^^^^^^^
[...]

You forgot to mark which line was redundant. Which line is it?

That one.
 
T

Thomas J. Gritzan

The line with the comment "// redundant" is redundant in the sense
that is never used in the main program. However, removing that line
will invalidate the program. I'm wondering if there is any way to
intelligently remove that line while still leaving the program
compilable.

Thanks,
Peng

#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>

class base {
public :
virtual ~base() {}
virtual void accept(base& b) = 0 ;
void visit() { } // redundant
};

template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
using Base::visit;
};

Remove the "using" declaration above, then you also can remove the
declaration of the function void visit().
 
B

BobR

Jim Langston wrote in message...
You forgot to mark which line was redundant. Which line is it?

Glad to see I'm not the only one with sight problems. <G>

Hi Jim.
 
A

Alf P. Steinbach

* Thomas J. Gritzan:
Remove the "using" declaration above, then you also can remove the
declaration of the function void visit().

I'm not familiar with boost::mpl, but I tried what you write because
that seemed sort of obvious, it didn't work, and I decided (after
looking at the documentation) that I had nothing to contribute --
otherwise, it might have been you writing this to me...

Except, to the OP, please explain your code (the fold thing).

I may be wrong, but others than me could possibly benefit from that.
 
T

Thomas J. Gritzan

Alf said:
* Thomas J. Gritzan:
(e-mail address removed) wrote: [...]
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>

class base {
public :
virtual ~base() {}
virtual void accept(base& b) = 0 ;
void visit() { } // redundant
};

template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
using Base::visit;
};

Remove the "using" declaration above, then you also can remove the
declaration of the function void visit().

I'm not familiar with boost::mpl, but I tried what you write because
that seemed sort of obvious, it didn't work, and I decided (after
looking at the documentation) that I had nothing to contribute --
otherwise, it might have been you writing this to me...

You are right. But we are here to discuss things, aren't we? :)

The using declaration is needed to merge all visit() member functions into
a class of a type like
visitor<visitor<Base,A>, B>

So when doing visitor<Base, T> there is no 'using' needed, but when Base
itself is a visitor, the code needs 'using' to compile. This can be done by
partial template specialisation:

template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
// using Base::visit; // not needed here.
};

template <typename Base, typename T1, typename T>
class visitor<visitor<Base, T1>,T> : public visitor<Base,T1> {
public :
virtual void visit(T &) = 0 ;
using visitor<Base,T1>::visit;
};

HTH (especially since I don't know boost.mpl)
 
P

PengYu.UT

Alf said:
* Thomas J. Gritzan:
(e-mail address removed) wrote: [...]
#include <iostream>
#include <boost/mpl/fold.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/placeholders.hpp>
class base {
public :
virtual ~base() {}
virtual void accept(base& b) = 0 ;
void visit() { } // redundant
};
template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
using Base::visit;
};
Remove the "using" declaration above, then you also can remove the
declaration of the function void visit().
I'm not familiar with boost::mpl, but I tried what you write because
that seemed sort of obvious, it didn't work, and I decided (after
looking at the documentation) that I had nothing to contribute --
otherwise, it might have been you writing this to me...

You are right. But we are here to discuss things, aren't we? :)

The using declaration is needed to merge all visit() member functions into
a class of a type like
visitor<visitor<Base,A>, B>

So when doing visitor<Base, T> there is no 'using' needed, but when Base
itself is a visitor, the code needs 'using' to compile. This can be done by
partial template specialisation:

template <typename Base, typename T>
class visitor : public Base {
public :
virtual void visit(T &) = 0 ;
// using Base::visit; // not needed here.

};

template <typename Base, typename T1, typename T>
class visitor<visitor<Base, T1>,T> : public visitor<Base,T1> {
public :
virtual void visit(T &) = 0 ;
using visitor<Base,T1>::visit;

};

HTH (especially since I don't know boost.mpl)

That is exact what I meant. I need the ability to tell the difference
between the list head and other elements of the list. For the head of
the list, there is no need to "using visit", because there is nothing
to use. For the subsequent elements, I need to "using visit" get the
"visit" function from the base class into the derived class.

Thanks,
Peng
 
A

Alf P. Steinbach

* (e-mail address removed):
That is exact what I meant. I need the ability to tell the difference
between the list head and other elements of the list. For the head of
the list, there is no need to "using visit", because there is nothing
to use. For the subsequent elements, I need to "using visit" get the
"visit" function from the base class into the derived class.

I think perhaps the Real Problem(TM) may be something else.

If the problem is how to get the "everybody can visit each other"
working, try

#include <iostream>
#include <ostream>

void say( char const s[] ) { std::cout << s << std::endl; }

class A;
class B;

class IVisitor
{
public:
virtual ~IVisitor() {}
virtual void visit( A& ) = 0;
virtual void visit( B& ) = 0;
};

class IAcceptor
{
public:
virtual ~IAcceptor() {}
virtual void accept( IVisitor& v ) = 0;
};

class ISocial: public virtual IVisitor, public virtual IAcceptor
{};

class A: public ISocial
{
public :
void visit( A& ) { say( "A-A"); }
void visit( B& ) { say( "A-B" ); }
void accept( IVisitor& v ) { v.visit( *this ); }
};

class B: public ISocial
{
public :
void visit( A& ) { say( "B-A" ); }
void visit( B& ) { say( "B-B" ); }
void accept( IVisitor& v) { v.visit(*this); }
};

int main()
{
A a;
B b;
ISocial& ra = a ;
ISocial& rb = b ;

ra.accept( ra ); // A-A
rb.accept( ra ); // A-B
ra.accept( rb ); // B-A
rb.accept( rb ); // B-B
}

No need to bring in type list machinery etc., casting etc. (note: the
purpose of the visitor pattern is to /centralize/ any downcasting!);
that's over-engineering.

But I think the idea of everybody visiting each other is perhaps not
very sound, itself possibly a case of over-engineering or over-abstraction.

Instead, perhaps the needs of each particular class indicate some more
limited application of the visitor pattern.

Cheers,

- Alf
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,579
Members
45,053
Latest member
BrodieSola

Latest Threads

Top