Welcome, Guest. Please login or register.

Login with username, password and session length

 
Advanced search

1411917 Posts in 69431 Topics- by 58477 Members - Latest Member: KriegsHetzer

June 10, 2024, 04:37:47 PM

Need hosting? Check out Digital Ocean
(more details in this thread)
TIGSource ForumsDeveloperTechnical (Moderator: ThemsAllTook)Passing functions as template parameters
Pages: 1 [2]
Print
Author Topic: Passing functions as template parameters  (Read 6026 times)
Crimsontide
Level 5
*****


View Profile
« Reply #20 on: May 29, 2010, 12:42:13 PM »

Did Average's suggestion about variadic templates work?

I'd love to try variadic templates, unfortunetly VC++ doesn't support them yet.  I decided to go with this solution:

Code:
template <typename T, T& F> void WrapperFunction () { /* stuff */ }
#define Wrap(X) WrapperFunction<decltype(X),X>()

Which works quite well.  Most often I want to do this sort of thing its for optimization, but here I needed the function as a template parameter because I needed it embedded in the type.

I was working on a recursive decent parser, but I wanted everything short of the actual parsing to be done with metaprogramming (mostly as an excuse to learn some new tricks/techniques).  Generally it works along the lines of:

Code:
auto digit = 0 | 1 | 2 | 3;   // ect....
auto num = +digit;
auto if = i >> f;
auto then = t >> h >> e >> n;
auto else = e >> l >> s >> e;
auto end = e >> n >> d;
auto ifelse = if >> expr >> then >> exp >> !(else >> exp) >> end;   // ! = 1 or none, expr defined elsewhere
auto p = SemanticAction(SomeFunc,ifelse);
// ect...

// parse
std::string str("stuff here to be parsed");
std::string::iterator i = str.begin();
Parse(p,i,str.end());

I needed to be able to add a semantic action, a function that would execute when a parser was recognized.  The thing here was, it needed to be a template parameter because all the parsing info is embedded in the type.

All in all it was a fun exercise, much was learned, and its nice to have something usable at the end of it all ; )
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #21 on: May 29, 2010, 01:00:20 PM »

Did Average's suggestion about variadic templates work?

Testing on gcc 4.4, the following works:

Code:
#include <iostream>

using std::cout;
using std::endl;

template <typename FuncType, typename... Args>
inline void Call(FuncType funk, Args... args)
{
    funk(args...);
}

void Zero()
{
    cout << "zero\n";
}

void One(int x)
{
    cout << "one: " << x << endl;
}

void Two(int x, int y)
{
    cout << "two: " << x << ' ' << y << endl;
}

int main()
{
    Call(Zero);
    Call(One, 5);
    Call(Two, 3, 10);
}
Logged



What would John Carmack do?
increpare
Guest
« Reply #22 on: May 29, 2010, 01:07:45 PM »

I like!
Logged
Crimsontide
Level 5
*****


View Profile
« Reply #23 on: May 29, 2010, 01:44:13 PM »

Did Average's suggestion about variadic templates work?

Testing on gcc 4.4, the following works:

Code:
#include <iostream>

using std::cout;
using std::endl;

template <typename FuncType, typename... Args>
inline void Call(FuncType funk, Args... args)
{
    funk(args...);
}

void Zero()
{
    cout << "zero\n";
}

void One(int x)
{
    cout << "one: " << x << endl;
}

void Two(int x, int y)
{
    cout << "two: " << x << ' ' << y << endl;
}

int main()
{
    Call(Zero);
    Call(One, 5);
    Call(Two, 3, 10);
}

That's pretty sweet ; )
Logged
Crimsontide
Level 5
*****


View Profile
« Reply #24 on: May 29, 2010, 06:20:08 PM »

For those who might be following this thread...  I made a really silly mistake Facepalm  I can't believe it either, I really should've known better. 

So after playing around with what I thought was a fully working recursive decent parser, realized that I can't use recursion in the grammar definition, which means it isn't a true context free parser.  Its pretty much just a fancy (and hence slow) regular expression parser, which would be far better off parsed using a FSM.

The whole reason for this thread (passing functions as template arguments) still stands, but I still feel quite stupid I didn't catch such an obvious mistake FAR earlier.  Thanks for the responses anyways.
Logged
Mikademus
Level 10
*****


The Magical Owl


View Profile
« Reply #25 on: May 30, 2010, 10:06:40 AM »

Hey, it is an interesting question nonetheless, and a good thread!

Average, good to see that we can use variadic arguments that way. Is there any way of obtaining the return type of the function so we can use that in the template declaration?
Logged

\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
BlueSweatshirt
Level 10
*****

the void


View Profile WWW
« Reply #26 on: May 30, 2010, 10:11:45 AM »

Did Average's suggestion about variadic templates work?

Testing on gcc 4.4, the following works:

Code:
#include <iostream>

using std::cout;
using std::endl;

template <typename FuncType, typename... Args>
inline void Call(FuncType funk, Args... args)
{
    funk(args...);
}

void Zero()
{
    cout << "zero\n";
}

void One(int x)
{
    cout << "one: " << x << endl;
}

void Two(int x, int y)
{
    cout << "two: " << x << ' ' << y << endl;
}

int main()
{
    Call(Zero);
    Call(One, 5);
    Call(Two, 3, 10);
}

If I knew about that whole "args..." thing, my life would have been so much easier over so many occasions.  Facepalm

[EDIT]
Ahhh, it's a C++0x thing. Just found out by testing the code myself.

I just found a reason to truly love C++0x. Kiss
« Last Edit: May 30, 2010, 10:19:14 AM by Jakman4242 » Logged

Crimsontide
Level 5
*****


View Profile
« Reply #27 on: May 30, 2010, 01:30:50 PM »

Hey, it is an interesting question nonetheless, and a good thread!

Average, good to see that we can use variadic arguments that way. Is there any way of obtaining the return type of the function so we can use that in the template declaration?

I would assume (but haven't tested) you could extract them much like you do now with:

Code:
template <typename T> struct GetReturnType {};
template <typaneme TR, typename... ARGS> struct GetReturnType<TR (ARGS...)> { typedef TR type; };

I can't test it with VC++ yet (no variadic templates yet), and haven't had the time to install GCC.  So its just a guess...
Logged
Average Software
Level 10
*****

Fleeing all W'rkncacnter


View Profile WWW
« Reply #28 on: May 30, 2010, 01:53:42 PM »

Hey, it is an interesting question nonetheless, and a good thread!

Average, good to see that we can use variadic arguments that way. Is there any way of obtaining the return type of the function so we can use that in the template declaration?

Yes.

Code:
#include <iostream>

using std::cout;
using std::endl;

template <typename FuncType, typename... Args>
inline auto Call(FuncType funk, Args... args) -> decltype(funk(args...))
{
    return funk(args...);
}

void Zero()
{
    cout << "zero\n";
}

void One(int x)
{
    cout << "one: " << x << endl;
}

void Two(int x, int y)
{
    cout << "two: " << x << ' ' << y << endl;
}

int RetInt()
{
    return 5;
}

float RetFloat()
{
    return 2.5;
}

int main()
{
    Call(Zero);
    Call(One, 5);
    Call(Two, 3, 7);

    cout << Call(RetInt) << endl;
    cout << Call(RetFloat) << endl;
}
Logged



What would John Carmack do?
Mikademus
Level 10
*****


The Magical Owl


View Profile
« Reply #29 on: May 31, 2010, 02:29:55 AM »

Thanks! That's very high-level, and possibly highly useful!
Logged

\\\"There\\\'s a tendency among the press to attribute the creation of a game to a single person,\\\" says Warren Spector, creator of Thief and Deus Ex. --IGN<br />My compilation of game engines for indies
Pages: 1 [2]
Print
Jump to:  

Theme orange-lt created by panic