instantiating template functions and classes with boost preprocess - c++

Working with the seemingly standard w, x, y, z demos, suppose I have the following macro trying to be converted to an "iterable" preprocessor macro
#define INSTANTIATE_FUNC(rtype, func_name, ...) \
template rtype func_name< w > (__VA_ARGS__); \
template rtype func_name< x > (__VA_ARGS__); \
template rtype func_name< y > (__VA_ARGS__); \
template rtype func_name< z > (__VA_ARGS__);
For completeness, suppose we're trying to instantiate the following
struct w { static constexpr int data = 0; };
struct x { static constexpr int data = 1; };
struct y { static constexpr int data = 2; };
struct z { static constexpr int data = 3; };
template <class Data>
void printData(const std::string &prefix) {
std::cout << prefix << Data::data << std::endl;
}
INSTANTIATE_FUNC(void, printData, const std::string &prefix)
I made a minimal gist with a build system for convenience so that if you are interested in trying you don't have to recreate everything :)
I can't quite figure out how to approach this. The only functional (but not useful) stab
#include <boost/preprocessor/list/for_each.hpp>
#define LIST (w, (x, (y, (z, BOOST_PP_NIL))))
#define MACRO(r, data, elem) template void data < elem > (const std::string &prefix);
#define INSTANTIATE_FUNC(rtype, func_name, ...) \
BOOST_PP_LIST_FOR_EACH(MACRO, func_name, LIST)
This is works, but is clearly not adequate.
Why does this not also work with sequences?
#include <boost/preprocessor/seq/for_each.hpp>
// this does work, my code included the wrong header
// on what I was testing with (seq/for_each_i.hpp)
#define SEQ (x)(y)(z)(w)
#define INSTANTIATE_FUNC(rtype, func_name, ...) \
BOOST_PP_SEQ_FOR_EACH(MACRO, func_name, SEQ)
How should I approach building template rtype func_name < {w,x,y,z} > {args,in,__VA_ARGS__}? I tried quite a few different things, but the problem seems to be not being able to e.g. only extract w and then loop through __VA_ARGS__, then continue on. I've been trying like heck to get BOOST_PP_LIST_FOR_EACH_R to work. Is this at least the right thing to look at?
As a sanity check, you can't define a macro within a macro right? Something in the spirit of
#define INSTANTIATE_FUNC(rtype, func_name, ...) \
#define MACRO_##func_name(r, data, elem) data < elem > (__VA_ARGS__); \
BOOST_PP_LIST_FOR_EACH(MACRO_##func_name, func_name, LIST)
I'm ultimately working toward the goal of enabling optional extension of LIST / SEQ (SEQ seeming much easier to achieve this for) if that means anything. Thanks for any suggestions / resources.

Your problem seems to be that you need to deliver several pieces of data to your MACRO in BOOST_PP_(LIST|SEQ)_FOR_EACH and there is only one "slot" that you can use. The thing that you seem to be missing is the fact that you can group those pieces in, for example, a tuple and then access the different elements inside your MACRO using BOOST_PP_TUPLE_ELEM. Something like this could work:
//These are not required, just to help with readability
#define MACRO_GET_RETURN_TYPE(TUPLE) BOOST_PP_TUPLE_ELEM(3,0,TUPLE)
#define MACRO_GET_FUNC_NAME(TUPLE) BOOST_PP_TUPLE_ELEM(3,1,TUPLE)
#define MACRO_GET_ARGS_SEQ(TUPLE) BOOST_PP_TUPLE_ELEM(3,2,TUPLE)
#define MACRO(_, DATA, ELEM) template MACRO_GET_RETURN_TYPE(DATA) MACRO_GET_FUNC_NAME(DATA) < ELEM > (BOOST_PP_SEQ_ENUM(MACRO_GET_ARGS_SEQ(DATA)));
// with boost seq
#define SEQ (x)(y)(z)(w)
#define INSTANTIATE_FUNC(rtype, func_name, ...) \
BOOST_PP_SEQ_FOR_EACH(MACRO, (rtype,func_name,BOOST_PP_VARIADIC_TO_SEQ(__VA_ARGS__)), SEQ)
Live on Wandbox
PS: No, you can't define a macro within a macro, and the code you posted here does work for sequences, the one in your gist does not due to using the wrong header.

Related

Creating enum from variadic arguments?

In some other langauges you can specify enums along with states, eg.:
public enum Planet {
MERCURY (3.303e+23, 2.4397e6),
VENUS (4.869e+24, 6.0518e6),
EARTH (5.976e+24, 6.37814e6),
MARS (6.421e+23, 3.3972e6),
JUPITER (1.9e+27, 7.1492e7),
SATURN (5.688e+26, 6.0268e7),
URANUS (8.686e+25, 2.5559e7),
NEPTUNE (1.024e+26, 2.4746e7);
...
This isn't hard to emulate in c++ - but only it easily becomes somewhat verbose.
I know this has been asked before and similar questions exists, e.g. in Build an enum using variadic template parameters, but I wanted to ask this again and have slightly different perspective.
Consider the following 'hand-written' approach:
#pragma warning(error : 4062)
enum tvtype {
black_and_white,
color
};
struct TvType {
tvtype tvtype_;
constexpr TvType(tvtype type) : tvtype_{type} {
}
constexpr operator tvtype() const {
return tvtype_;
}
};
constexpr TvType BlackAndWhite(black_and_white);
constexpr TvType Color(color);
bool hasColor(TvType tv) {
switch (tv) {
case BlackAndWhite:
return false;
//case Color:
//return true;
};
return false;
}
Try it yourself (comment in the two lines in the switch to make it compile)
This method is working well - only it is somewhat verbose.
Using this method it should now be possible to store some extra information along with the enum value, like a string representation, perhaps adding functions as well, etc.
Also because it's actually an enum underneath, it's possible for the compiler to check that all cases have been checked in the switch (the example above should generates a compile error due that the 'color' case is outcommented).
I'm interested in a generic / templated way of getting the enum generated or something similar that fulfills the requirement of compiler checked switch and extensibility.
But in order to templatize the above, it seems the enum should be generated in a (compile-time) programatical way, which leads to the question:
Is it possible to create an enum from a fold expression for instance or failing that from some kind of recursive template ?
Is it possible to create an enum from a fold expression for instance or failing that from some kind of recursive template ?
Not with variadic templates. Template arguments can be types, or constant values. You can't substitute a symbol to stick it inside an enum block.
However, you can do that with macros. Only trouble is, while C++11 has something called "variadic macros", it's very limited.
#define MY_MACRO(...) enum { __VA_ARGS__ }
You can't do any kind of transformation on variadic arguments like you can with templates, it literally just replaces __VA_ARGS___ with all the tokens the ... represents.
But, using the technique from this great answer: https://stackoverflow.com/a/11763277/1863938 , you can support "up to N" variadic solutions. Using that, you can create a macro that templates your boilerplate class for up to N values. Below is for up to 4 symbols:
#define _JENUM_GET_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define _JENUM_VALUE_DEF1(_1) _##_1##_v_
#define _JENUM_VALUE_DEF2(_1,_2) _JENUM_VALUE_DEF1(_1), _JENUM_VALUE_DEF1(_2)
#define _JENUM_VALUE_DEF3(_1,_2,_3) _JENUM_VALUE_DEF1(_1), _JENUM_VALUE_DEF1(_2), _JENUM_VALUE_DEF1(3)
#define _JENUM_VALUE_DEF4(_1,_2,_3,_4) _JENUM_VALUE_DEF1(_1), _JENUM_VALUE_DEF1(_2), _JENUM_VALUE_DEF1(3), _JENUM_VALUE_DEF1(_4)
#define _JENUM_VALUE_DEF(...) _JENUM_GET_MACRO(__VA_ARGS__, _JENUM_VALUE_DEF4, _JENUM_VALUE_DEF3, _JENUM_VALUE_DEF2, _JENUM_VALUE_DEF1)(__VA_ARGS__)
#define _JENUM_ENUM_DEF(name, ...) enum _##name##_e_ { _JENUM_VALUE_DEF(__VA_ARGS__) };
#define _JENUM_CLASS_DEF(name) struct name {\
_##name##_e_ _value;\
constexpr name(const name& that) : _value(that._value) { }\
constexpr name(_##name##_e_ _value) : _value(_value) { }\
constexpr operator _##name##_e_() const { return _value; }\
};\
#define _JENUM_CONST_DEF1(name, _1) constexpr name _1(_JENUM_VALUE_DEF1(_1));
#define _JENUM_CONST_DEF2(name, _1,_2) _JENUM_CONST_DEF1(name, _1) _JENUM_CONST_DEF1(name, _2)
#define _JENUM_CONST_DEF3(name, _1,_2,_3) _JENUM_CONST_DEF1(name, _1) _JENUM_CONST_DEF1(name, _2) _JENUM_CONST_DEF1(name, _3)
#define _JENUM_CONST_DEF4(name, _1,_2,_3,_4) _JENUM_CONST_DEF1(name, _1) _JENUM_CONST_DEF1(name, _2) _JENUM_CONST_DEF1(name, _3) _JENUM_CONST_DEF1(name, _4)
#define _JENUM_CONST_DEF(name, ...) _JENUM_GET_MACRO(__VA_ARGS__, _JENUM_CONST_DEF4, _JENUM_CONST_DEF3, _JENUM_CONST_DEF2, _JENUM_CONST_DEF1)(name, __VA_ARGS__)
#define JENUM(name, ...)\
_JENUM_ENUM_DEF(name, __VA_ARGS__)\
_JENUM_CLASS_DEF(name)\
_JENUM_CONST_DEF(name, __VA_ARGS__)
... just follow the pattern to add more overloads
Then, to use:
JENUM(TvType, BlackAndWhite, Color);
Now, if you want to add methods and whatnot, it's easier to just inherit than to try and work anything into the macro:
struct TvTypeEx : public TvType {
using TvType::TvType;
TvTypeEx(TvType that) : TvType(that) { }
bool hasColor() const { return *this == Color; }
};
Now you can do stuff like:
TvTypeEx tv = Color;
return tv.hasColor() ? GetColorContent() : GetBlackAndWhiteContent();
Demo: https://godbolt.org/z/rdqS65

Error contains no argument packs when redefine a macro [duplicate]

Say I have a macro like this:
#define SET_TYPE_NAME(TYPE, NAME) \
template<typename T> \
std::string name(); \
\
template<> \
std::string name<TYPE>() { \
return NAME; \
}
This won't work if I pass it a template that has more than one parameter, because the comma in the <int, int> is interpreted as separating the macro arguments, not the template arguments.
SET_TYPE_NAME(std::map<int, int>, "TheMap")
// Error: macro expects two arguments, three given
This problem seems to be solved by doing this:
SET_TYPE_NAME((std::map<int, int>), "TheMap")
But now another problem arises, one that I really did not expect:
template<>
std::string name<(std::map<int, int>)>()
// template argument 1 is invalid
It seems that the extra parentheses make the template argument invalid. Is there any way around this?
Besides typedef, you could switch the order of the arguments and use variadic macros (requires C99 or C++11-compatible compiler):
#define SET_TYPE_NAME(NAME, ...) \
template<typename T> \
std::string name(); \
\
template<> \
std::string name<__VA_ARGS__>() { \
return NAME; \
}
...
SET_TYPE_NAME("TheMap", std::map<int, int>)
You could use typedef:
typedef std::map<int, int> int_map;
SET_TYPE_NAME(int_map, "TheMap");
boost's BOOST_FOREACH suffers from the same issue.
Some time ago (while searching the web for the utility of Identity<T>) I got to this page.
In brief, to answer the question, if you don't have C++11 support and/or can't (or don't want to) use a typedef, you call your macro the "right" way:
// If an argument contains commas, enclose it in parentheses:
SET_TYPE_NAME((std::map<int, int>), "TheMap")
// For an argument that doesn't contain commas, both should work:
SET_TYPE_NAME((SomeType1), "TheType1")
SET_TYPE_NAME(SomeType2, "TheType2")
and then to get rid of the (possible) unwanted parentheses around the type, you can use a "helper" like this:
template<typename> struct RemoveBrackets;
template<typename T> struct RemoveBrackets<void (T)> {
typedef T Type;
};
and in your macro change the line:
std::string name<TYPE>() { \
to:
std::string name< RemoveBrackets<void (TYPE)>::Type >() { \
(or define a helper macro, say
#define REMOVE_BRACKETS(x) RemoveBrackets<void (x)>::Type
then replace the line with
std::string name< REMOVE_BRACKETS(TYPE) >() { \
).
(For the full story read the paragraph "An even better solution" at the end of the article linked above.)
Edit: just found that. But it uses <void X> when it really should use <void (X)> (in get_first_param<void X>::type); indeed the parentheses are necessary if you pass a "simple", non-bracketed argument (like SomeType2 in my code above) -- and they don't hurt if X is already bracketed (e.g., void ((SomeType1)) is equivalent to void (SomeType1); again, see the article). (By the way, I noticed that many answers on the other SO page are in essence "Macros are dumb". I won't comment, though.)
I'd like to add an answer to my own question. Now that Boost 1.50.0 was released, Boost.Utility has a new mini-library that helps with this kind of thing. If you look at the source you'll see it's implemented the same as gx_'s solution. Here's how to use it:
#include <boost/utility/identity_type.hpp>
SET_TYPE_NAME(BOOST_IDENTITY_TYPE((std::map<int, int>)), "TheMap");
http://www.boost.org/doc/libs/1_50_0/libs/utility/identity_type/doc/html/index.html
I like the typedef way proposed by hmjd better, but for the record, the usual way I've seen around this is to kick the angle brackets out of the macro and write:
#define SET_TYPE_NAME(TYPE, NAME) \
template<typename T> \
std::string name(); \
\
template<> \
std::string name TYPE() { \
return NAME; \
}
Usage:
SET_TYPE_NAME(<std::map<int, int> >, "TheMap")
This is a variation of an old technique used for error message reporting and fprintf:
#define Error(args) do { \
printf("ERROR: "); \
printf args; \
printf("\n"); \
return 1; \
} while(0)
Called with:
Error(("Index out of range: %d not in %d ... %d.", var, min, max));
It's ugly but it worked. Useful if the coding style rules ban typedef.
typedef std::map<int,int> IntMap_t;
SET_TYPE_NAME(IntMap_t, "TheMap")
You can declare a typedef and use it in the macro
A more generic way is to always use () around your arguments that may contain a comma and use CONCAT to remove the parenthesis. If you do so, you can define multiple parameters packs wits comma inside or put arguments in your favorite order
#ifndef CONCAT
#define CONCAT __VA_ARGS__
#endif
#define MYMACRO(tparam,classname)\
template < CONCAT tparam >\
class CONCAT classname {};
//create a template class X<T,U>
MYMACRO( (typename T,typename U) , (X<T,U>) )
I know this is an old question. Though this comes in top results on a Google search and nobody has yet mentioned an even more simple solution by defining a macro for the comma:
#define COMMA ,
SET_TYPE_NAME(std::map<int COMMA int>, "TheMap")

PreProcessor: store array of strings at compile-time

I need a container of strings at compile-time, which should be iterable at runtime.
However, I really need a macro, so that some functions will be produced (can't think of a way to do that with templated code at namespace-level).
But in the following code I get 'error: 'sequence' in 'class LaLaLa' does not name a type', which happens within the ASSIGN macro (I think).
Can somebody help me with this?
#define CREATE_FUNCTION(r, data, i, elem) // creates a function with name 'do_something_with_##elem()'
#define ASSIGN(r, data, i, elem) data::sequence[i] = elem;
#define TO_ARRAY(name, _seq) \
BOOST_PP_SEQ_FOR_EACH(CREATE_FUNCTION, _, _seq) \
class name \
{ \
public: \
static constexpr std::size_t size = BOOST_PP_SEQ_SIZE(_seq); \
static std::string sequence[size]; \
}; \
BOOST_PP_SEQ_FOR_EACH_I(ASSIGN, name, _seq)
TO_ARRAY(LaLaLa, (x)(y)(z)(a))
Then I would like to use it something like this:
do_something_with_x();
do_something_with_z();
std::vector<std::string> use_strings;
for(size_t i = 0; i < LaLaLa::size; ++i)
{
use_strings.push_back(LaLaLa::sequence[i]);
}
// use_strings == {"x", "y", "z", "a"}
The problem wasn't the preprocessor - using the sequence directly after the class definition is the problem. (needs to be done within a function or something like that)

How to pass multi-argument templates to macros?

Say I have a macro like this:
#define SET_TYPE_NAME(TYPE, NAME) \
template<typename T> \
std::string name(); \
\
template<> \
std::string name<TYPE>() { \
return NAME; \
}
This won't work if I pass it a template that has more than one parameter, because the comma in the <int, int> is interpreted as separating the macro arguments, not the template arguments.
SET_TYPE_NAME(std::map<int, int>, "TheMap")
// Error: macro expects two arguments, three given
This problem seems to be solved by doing this:
SET_TYPE_NAME((std::map<int, int>), "TheMap")
But now another problem arises, one that I really did not expect:
template<>
std::string name<(std::map<int, int>)>()
// template argument 1 is invalid
It seems that the extra parentheses make the template argument invalid. Is there any way around this?
Besides typedef, you could switch the order of the arguments and use variadic macros (requires C99 or C++11-compatible compiler):
#define SET_TYPE_NAME(NAME, ...) \
template<typename T> \
std::string name(); \
\
template<> \
std::string name<__VA_ARGS__>() { \
return NAME; \
}
...
SET_TYPE_NAME("TheMap", std::map<int, int>)
You could use typedef:
typedef std::map<int, int> int_map;
SET_TYPE_NAME(int_map, "TheMap");
boost's BOOST_FOREACH suffers from the same issue.
Some time ago (while searching the web for the utility of Identity<T>) I got to this page.
In brief, to answer the question, if you don't have C++11 support and/or can't (or don't want to) use a typedef, you call your macro the "right" way:
// If an argument contains commas, enclose it in parentheses:
SET_TYPE_NAME((std::map<int, int>), "TheMap")
// For an argument that doesn't contain commas, both should work:
SET_TYPE_NAME((SomeType1), "TheType1")
SET_TYPE_NAME(SomeType2, "TheType2")
and then to get rid of the (possible) unwanted parentheses around the type, you can use a "helper" like this:
template<typename> struct RemoveBrackets;
template<typename T> struct RemoveBrackets<void (T)> {
typedef T Type;
};
and in your macro change the line:
std::string name<TYPE>() { \
to:
std::string name< RemoveBrackets<void (TYPE)>::Type >() { \
(or define a helper macro, say
#define REMOVE_BRACKETS(x) RemoveBrackets<void (x)>::Type
then replace the line with
std::string name< REMOVE_BRACKETS(TYPE) >() { \
).
(For the full story read the paragraph "An even better solution" at the end of the article linked above.)
Edit: just found that. But it uses <void X> when it really should use <void (X)> (in get_first_param<void X>::type); indeed the parentheses are necessary if you pass a "simple", non-bracketed argument (like SomeType2 in my code above) -- and they don't hurt if X is already bracketed (e.g., void ((SomeType1)) is equivalent to void (SomeType1); again, see the article). (By the way, I noticed that many answers on the other SO page are in essence "Macros are dumb". I won't comment, though.)
I'd like to add an answer to my own question. Now that Boost 1.50.0 was released, Boost.Utility has a new mini-library that helps with this kind of thing. If you look at the source you'll see it's implemented the same as gx_'s solution. Here's how to use it:
#include <boost/utility/identity_type.hpp>
SET_TYPE_NAME(BOOST_IDENTITY_TYPE((std::map<int, int>)), "TheMap");
http://www.boost.org/doc/libs/1_50_0/libs/utility/identity_type/doc/html/index.html
I like the typedef way proposed by hmjd better, but for the record, the usual way I've seen around this is to kick the angle brackets out of the macro and write:
#define SET_TYPE_NAME(TYPE, NAME) \
template<typename T> \
std::string name(); \
\
template<> \
std::string name TYPE() { \
return NAME; \
}
Usage:
SET_TYPE_NAME(<std::map<int, int> >, "TheMap")
This is a variation of an old technique used for error message reporting and fprintf:
#define Error(args) do { \
printf("ERROR: "); \
printf args; \
printf("\n"); \
return 1; \
} while(0)
Called with:
Error(("Index out of range: %d not in %d ... %d.", var, min, max));
It's ugly but it worked. Useful if the coding style rules ban typedef.
typedef std::map<int,int> IntMap_t;
SET_TYPE_NAME(IntMap_t, "TheMap")
You can declare a typedef and use it in the macro
A more generic way is to always use () around your arguments that may contain a comma and use CONCAT to remove the parenthesis. If you do so, you can define multiple parameters packs wits comma inside or put arguments in your favorite order
#ifndef CONCAT
#define CONCAT __VA_ARGS__
#endif
#define MYMACRO(tparam,classname)\
template < CONCAT tparam >\
class CONCAT classname {};
//create a template class X<T,U>
MYMACRO( (typename T,typename U) , (X<T,U>) )
I know this is an old question. Though this comes in top results on a Google search and nobody has yet mentioned an even more simple solution by defining a macro for the comma:
#define COMMA ,
SET_TYPE_NAME(std::map<int COMMA int>, "TheMap")

How can one make a 'passthru' function in C++ using macros or metaprogramming?

So I have a series of global functions, say:
foo_f1(int a, int b, char *c);
foo_f2(int a);
foo_f3(char *a);
I want to make a C++ wrapper around these, something like:
MyFoo::f1(int a, int b, char* c);
MyFoo::f2(int a);
MyFoo::f3(char* a);
There's about 40 functions like this, 35 of them I just want to pass through to the global function, the other 5 I want to do something different with.
Ideally the implementation of MyFoo.cpp would be something like:
PASSTHRU( f1, (int a, int b, char *c) );
PASSTHRU( f2, (int a) );
MyFoo::f3(char *a)
{
//do my own thing here
}
But I'm having trouble figuring out an elegant way to make the above PASSTHRU macro.
What I really need is something like the mythical X getArgs() below:
MyFoo::f1(int a, int b, char *c)
{
X args = getArgs();
args++; //skip past implicit this..
::f1(args); //pass args to global function
}
But short of dropping into assembly I can't find a good implementation of getArgs().
You could use Boost.Preprocessor to let the following:
struct X {
PASSTHRU(foo, void, (int)(char))
};
... expand to:
struct X {
void foo ( int arg0 , char arg1 ) { return ::foo ( arg0 , arg1 ); }
};
... using these macros:
#define DO_MAKE_ARGS(r, data, i, type) \
BOOST_PP_COMMA_IF(i) type arg##i
#define PASSTHRU(name, ret, args) \
ret name ( \
BOOST_PP_SEQ_FOR_EACH_I(DO_MAKE_ARGS, _, args) \
) { \
return ::name ( \
BOOST_PP_ENUM_PARAMS(BOOST_PP_SEQ_SIZE(args), arg) \
); \
}
At 40-odd functions, you could type the wrappers out by hand in an hour. The compiler will check the correctness of the result. Assume an extra 2 minutes for each new function that needs wrapping, and an extra 1 minute for a change in signature.
As specified, and with no mention of frequent updates or changes, it doesn't sound like this problem requires a cunning solution.
So, my recommendation is to keep it simple: do it by hand. Copy prototypes into source file, then use keyboard macros (emacs/Visual Studio/vim) to fix things up, and/or multiple passes of search and replace, generating one set of definitions and one set of declarations. Cut declarations, paste into header. Fill in definitions for the non-passing-through functions. This won't win you any awards, but it'll be over soon enough.
No extra dependencies, no new build tools, works well with code browsing/tags/intellisense/etc., works well with any debugger, and no specialized syntax/modern features/templates/etc., so anybody can understand the result. (It's true that nobody will be impressed -- but it will be the good kind of unimpressed.)
Slightly different syntax but...
#include <boost/preprocessor.hpp>
#include <iostream>
void f1(int x, int y, char* z) { std::cout << "::f1(int,int,char*)\n"; }
#define GENERATE_ARG(z,n,unused) BOOST_PP_CAT(arg,n)
#define GET_ARGS(n) BOOST_PP_ENUM(n, GENERATE_ARG, ~)
#define GENERATE_PARAM(z,n,seq) BOOST_PP_SEQ_ELEM(n,seq) GENERATE_ARG(z,n,~)
#define GENERATE_PARAMS(seq) BOOST_PP_ENUM( BOOST_PP_SEQ_SIZE(seq), GENERATE_PARAM, seq )
#define PASSTHROUGH(Classname, Function, ArgTypeSeq) \
void Classname::Function( GENERATE_PARAMS(ArgTypeSeq) ) \
{ \
::Function( GET_ARGS( BOOST_PP_SEQ_SIZE(ArgTypeSeq) ) ); \
}
struct test
{
void f1(int,int,char*);
};
PASSTHROUGH(test,f1,(int)(int)(char*))
int main()
{
test().f1(5,5,0);
std::cin.get();
}
You could get something closer to yours if you use tuples, but you'd have to supply the arg count to the base function (you can't derive a size from a tuple). Sort of like so:
PASSTHROUGH(test,f1,3,(int,int,char*))
That about what you're looking for? I knew it could be done; took about a half hour to solve. You seem to expect that there's an implicit 'this' that has to be gotten rid of but I don't see why...so maybe I misunderstand the problem. At any rate, this will let you quickly make default "passthrough" member functions that defer to some global function. You'll need a DECPASSTHROUGH for the class declaration if you want to skip having to declare them all...or you could modify this to make inline functions.
Hint: Use BOOST_PP_STRINGIZE((XX)) to test the output of preprocessor metafunctions.
My initial thought, and this probably won't work or others would have stated this, is to put all your base functions together in a class as virtual. Then, write the functionality improvements into inherited classes and run with it. It's not a macro wrapper, but you could always call the global functions in the virtual classes.
With some assembly trickery, you could probably do exactly what you'd want, but you would lose portability more than likely. Interesting question and I want to hear other's answers as well.
You may want to use a namespace if you want to not deal with class stuff, like this. You could also use static member methods in a class, but I think that people don't like that anymore.
#ifndef __cplusplus
#define PASSTHRU(type, prefix, func, args) type prefix##_##func args
#else
#define PASSTHRU(type, prefix, func, args) type prefix::func args
#endif
Or
#ifndef __cplusplus
#define PASSTHRU(type, prefix, func, ...) type prefix##_##func(__VA_ARGS__)
...
Perfect forwarding relies on rvalue references. STL has a blog entry on it at Link and you would want to choose a compiler that supported the feature to take this approach. He's discussing Visual C++ 2010.