I was looking for a way to do MultiMethods when I came across Loki.
Unfortunately, I can not get StaticDispatcher to work correctly (it always switches the types of rhs and lhs around for some reason), so I decided to try the BasicFastDispatch
In the book Modern C++ Design. However, I found there was no code snippet for this.
So I could type it in by hand, but I'm wondering why this dispatcher has not been included in the library.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Sorry, as of this time there is no implementation of BasicFastDispatcher in Loki. Oddly enough, I didn't even realize that until very recently when another reader has asked for it.
I'm busy now but I had put the item on my todo list. (If anyone has it, let me know and I'll add it with due credit.)
In the meantime, if you could post your code that displays an error in StaticDispatcher, that would be helpful.
Andrei
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
namespace Scenegraph
{
class IBase
class IActor : public IBase
class CModel : public IActor
}
class CPlayer : public Scenegraph::CModel
Note that player and model are not pointers to the base class, but this is only a test case. When I do start to really use the MultiMethod, I will only have pointers to the base class available.
I have tried to compile the code on Visual C++ Express Beta and gotten the following compiler error:
error C2664: 'CollisionExecuter::Fire' : cannot convert parameter 1 from 'Scenegraph::CModel' to 'CPlayer &'
If I switch the two parameters player and model around I get the same exact error. You'll notice that the Fire function I've provided has the arguments in CPlayer, CModel order (most derived class is first argument).
For a test I add another Fire functions with the two arguments switched around. This gave me the following error:
error C2666: 'CollisionExecuter::Fire' : 2 overloads have similar conversions
Then I removed the original Fire leaving me with only
void Fire( ::Scenegraph::CModel& t, CPlayer& p ); and still calling with CollisionDispatcher::Go(*model, *player, exec);
This gave me the following error:
error C2664: 'CollisionExecuter::Fire' : cannot convert parameter 2 from 'Scenegraph::CModel' to 'CPlayer &'
This is why I concluded that somehow the lhs and rhs get mixed up. I'll see if I can test this on a different compiler today, and report back with the results.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I've tried to compiler the project on Linux now using gcc 3.3.2.
In that case I got an error that
void Fire( Scenegraph::CModel&, Scengraph::CModel& ) wasn't defined.
After adding that function it seems to compile. Seems to, because I've got a different error, not related to Loki, which I haven't been able to solve yet. Therefore I haven't been able to actually run the program to see if StaticDispatcher works correctly.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have just purchased Modern C++ Design with the hopes of understanding the BasicFastDispatcher (although I don't see what's 'Basic' about it!). Some code would really help. The closest thing I've been able to find is the 'cooperative visitor' (http://www.artima.com/cppsource/cooperative_visitor.html) which seems to operate along similar lines.
I'm was surprised to find that it wasn't available in the Loki library. I'm the only one excited by it?
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I have just tried to compile the same project using Dev-C++ 4.9.9.2 (which uses GCC 3.4.2 according to the website) and have been able to get a compiled StaticDispatcher by adding overloads for all combinations of CPlayer and CModel (4 in total).
However, under this compiler, Loki has trouble compiling Singleton. It gives on line 105 (std::realloc), 158 (std::malloc) and 166(std::free) that these functions are not members of std. Removing std:: from these lines solves the problem. But after solving these problems, I get errors on lines 148 and 160 of SmallObj.h: abstract declarator `void*' used as declaration
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
While doing the tests with Dev-C++ I have been able to fix the errors in Visual C++ Express. This now compiles, and runs correctly.
What I needed to do was add a Fire(CModel, CModel) overload:
class CollisionExecuter
{
public:
void Fire( CPlayer& p, ::Scenegraph::CModel& t );
void Fire( ::Scenegraph::CModel& p, ::Scenegraph::CModel& t );
void OnError( ::Scenegraph::IBase& a, ::Scenegraph::IBase& b );
};
I am not entirely sure why this was required, since I am positive that these need not be called (see the test case). But then I haven't been able to fully grasp everything in Modern C++ Design, so it is possible that these overload MUST be provided even though they are not used. Unfortunately the compiler error message isn't entirely clear on that.
So apparently the version that works on Linux is correct. Please note that I have not yet provided overloads for Fire(CPlayer, CPlayer) but the compiler is not complaining about that.
Thanks for the interest though and sorry to have bothered you.
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I supposed, that StticDispatcher is insensitive for TYPELIST params order (class hierarchy order), but code below demonstraits the opposite. Is it a bug &
// Class hierarchy:
class CBase { public: virtual ~CBase() {}; };
class CActor : public CBase { };
class CModel : public CActor {};
class CPlayer : public CModel {};
I was looking for a way to do MultiMethods when I came across Loki.
Unfortunately, I can not get StaticDispatcher to work correctly (it always switches the types of rhs and lhs around for some reason), so I decided to try the BasicFastDispatch
In the book Modern C++ Design. However, I found there was no code snippet for this.
So I could type it in by hand, but I'm wondering why this dispatcher has not been included in the library.
Sorry, as of this time there is no implementation of BasicFastDispatcher in Loki. Oddly enough, I didn't even realize that until very recently when another reader has asked for it.
I'm busy now but I had put the item on my todo list. (If anyone has it, let me know and I'll add it with due credit.)
In the meantime, if you could post your code that displays an error in StaticDispatcher, that would be helpful.
Andrei
Sorry about the other post. That is the structure for the BasicFastDispatch.
The following is the code for the faulty StaticDispatcher:
class CollisionExecuter
{
public:
void Fire( CPlayer& p, ::Scenegraph::CModel& t );
void OnError( ::Scenegraph::IBase& a, ::Scenegraph::IBase& b );
};
typedef ::Loki::StaticDispatcher
<
CollisionExecuter,
::Scenegraph::IBase,
TYPELIST_2(CPlayer, ::Scenegraph::CModel)
>
CollisionDispatcher;
Calling code:
CPlayer *player = ...
Scenegraph::CModel *model = ...
CollisionExecuter exec;
CollisionDispatcher::Go(*player, *model, exec);
Class hierarchy:
namespace Scenegraph
{
class IBase
class IActor : public IBase
class CModel : public IActor
}
class CPlayer : public Scenegraph::CModel
Note that player and model are not pointers to the base class, but this is only a test case. When I do start to really use the MultiMethod, I will only have pointers to the base class available.
I have tried to compile the code on Visual C++ Express Beta and gotten the following compiler error:
error C2664: 'CollisionExecuter::Fire' : cannot convert parameter 1 from 'Scenegraph::CModel' to 'CPlayer &'
If I switch the two parameters player and model around I get the same exact error. You'll notice that the Fire function I've provided has the arguments in CPlayer, CModel order (most derived class is first argument).
For a test I add another Fire functions with the two arguments switched around. This gave me the following error:
error C2666: 'CollisionExecuter::Fire' : 2 overloads have similar conversions
Then I removed the original Fire leaving me with only
void Fire( ::Scenegraph::CModel& t, CPlayer& p ); and still calling with CollisionDispatcher::Go(*model, *player, exec);
This gave me the following error:
error C2664: 'CollisionExecuter::Fire' : cannot convert parameter 2 from 'Scenegraph::CModel' to 'CPlayer &'
This is why I concluded that somehow the lhs and rhs get mixed up. I'll see if I can test this on a different compiler today, and report back with the results.
That's great, thanks! I set your code aside to pore over it, and I'm looking forward to hearing of any other tests you might be making.
Andrei
I've tried to compiler the project on Linux now using gcc 3.3.2.
In that case I got an error that
void Fire( Scenegraph::CModel&, Scengraph::CModel& ) wasn't defined.
After adding that function it seems to compile. Seems to, because I've got a different error, not related to Loki, which I haven't been able to solve yet. Therefore I haven't been able to actually run the program to see if StaticDispatcher works correctly.
I have just purchased Modern C++ Design with the hopes of understanding the BasicFastDispatcher (although I don't see what's 'Basic' about it!). Some code would really help. The closest thing I've been able to find is the 'cooperative visitor' (http://www.artima.com/cppsource/cooperative_visitor.html) which seems to operate along similar lines.
I'm was surprised to find that it wasn't available in the Loki library. I'm the only one excited by it?
I have just tried to compile the same project using Dev-C++ 4.9.9.2 (which uses GCC 3.4.2 according to the website) and have been able to get a compiled StaticDispatcher by adding overloads for all combinations of CPlayer and CModel (4 in total).
However, under this compiler, Loki has trouble compiling Singleton. It gives on line 105 (std::realloc), 158 (std::malloc) and 166(std::free) that these functions are not members of std. Removing std:: from these lines solves the problem. But after solving these problems, I get errors on lines 148 and 160 of SmallObj.h: abstract declarator `void*' used as declaration
While doing the tests with Dev-C++ I have been able to fix the errors in Visual C++ Express. This now compiles, and runs correctly.
What I needed to do was add a Fire(CModel, CModel) overload:
class CollisionExecuter
{
public:
void Fire( CPlayer& p, ::Scenegraph::CModel& t );
void Fire( ::Scenegraph::CModel& p, ::Scenegraph::CModel& t );
void OnError( ::Scenegraph::IBase& a, ::Scenegraph::IBase& b );
};
I am not entirely sure why this was required, since I am positive that these need not be called (see the test case). But then I haven't been able to fully grasp everything in Modern C++ Design, so it is possible that these overload MUST be provided even though they are not used. Unfortunately the compiler error message isn't entirely clear on that.
So apparently the version that works on Linux is correct. Please note that I have not yet provided overloads for Fire(CPlayer, CPlayer) but the compiler is not complaining about that.
Thanks for the interest though and sorry to have bothered you.
The calling code:
CollisionDispatcher d;
d.Add<CPlayer, ::Scenegraph::CModel>(Fire);
d.Go(*p, *model);
Classes:
class CPlayer : public Scenegraph::CModel
namespace Scenegraph
{
class CModel : public IActor
class IActor : public IBase
class IBase
}
Sorry my bad english... but:
I supposed, that StticDispatcher is insensitive for TYPELIST params order (class hierarchy order), but code below demonstraits the opposite. Is it a bug &
#include <loki\MultiMethods.h>
#include <string>
#include <assert.h>
// Class hierarchy:
class CBase { public: virtual ~CBase() {}; };
class CActor : public CBase { };
class CModel : public CActor {};
class CPlayer : public CModel {};
// Dispatch methods set
class CollisionExecuter {
public:
std::string Fire( CModel&, CModel& ) { return "CModel-CModel"; }
std::string Fire( CActor&, CActor& ) { return "CActor-CActor"; }
std::string Fire( CPlayer&, CPlayer& ){ return "CPlayer-CPlayer";}
std::string Fire( CPlayer&, CModel& ){ return "CPlayer-CModel";}
std::string Fire( CPlayer&, CActor& ){ return "CPlayer-CActor";}
std::string Fire( CModel&, CPlayer&){ return "CModel-CPlayer";}
std::string Fire( CModel&, CActor& ){ return "CModel-CActor";}
std::string Fire( CActor&, CPlayer&){ return "CActor-CPlayer";}
std::string Fire( CActor&, CModel&){ return "CActor-CModel";}
std::string Fire( CBase&, CBase& ) { return "CBase-CBase"; }
std::string OnError( CBase&, CBase&) { return "OnError"; }
};
// Valid StaticDispatcher
typedef ::Loki::StaticDispatcher
<
CollisionExecuter,
CBase,
LOKI_TYPELIST_3( CPlayer, CModel, CActor ) ,
false,
CBase,
LOKI_TYPELIST_3( CPlayer, CModel, CActor ) ,
std::string
>
RightDispatcher;
// Invalid StaticDispatcher
typedef ::Loki::StaticDispatcher
<
CollisionExecuter,
CBase,
LOKI_TYPELIST_3( CModel, CActor, CPlayer ) ,
false,
CBase,
LOKI_TYPELIST_3( CModel, CActor, CPlayer ) ,
std::string
>
WrongDispatcher;
// Calling code
void testMethod() {
// Calling code:
CBase *player = new CPlayer();
CBase *model = new CModel();
CBase *actor = new CActor();
CollisionExecuter exec;
// This assertions evaluates to true
assert( "CPlayer-CModel" == RightDispatcher::Go(*player, *model, exec) );
assert( "CActor-CModel" == RightDispatcher::Go(*actor, *model, exec));
assert( "CModel-CModel" == RightDispatcher::Go(*model, *model, exec));
// Assertions below fails !!!
assert( "CPlayer-CModel" == WrongDispatcher::Go(*player, *model, exec) );
assert( "CActor-CModel" == WrongDispatcher::Go(*actor, *model, exec));
assert( "CModel-CModel" == WrongDispatcher::Go(*model, *model, exec));
std::cin.get();
}