#include <iostream>
#include <string>
#include <map>
using namespace std;
template<typename A, typename B>
std::ostream &operator<<(std::ostream &o, const std::pair<A,B> &p) { return o << "(" << p.first << ", " << p.second << ")"; }
namespace NP {
template<typename A, typename B>
struct Comma;
template<typename Param_>
struct Assign;
}
template<typename A, typename B>
std::ostream &
operator<<(std::ostream &o, const NP::Comma<A,B> &comma);
template<typename T>
std::ostream &
operator<<(std::ostream &o, const NP::Assign<T> &assign);
namespace NP {
template<typename A, typename B>
struct Comma {
A first;
B second;
//to appease the compiler when trying to pattern-match the base-case:
typedef void *Value;
typedef void *Param;
Comma(const A &first_, const B &second_)
: first(first_) , second(second_) {}
typename B::Value
operator[](const typename B::Param &secondArg) const {
return second.value;
}
template<typename T>
typename T::Value
operator[](const T &firstArg) const {
return first[firstArg];
}
typename A::Value
operator[](const typename A::Param &firstArg) const {
return first.value;
}
};
template<typename Param_>
struct Assign {
typedef Param_ Param;
typedef typename Param::Value Value;
const Value &value;
Assign(const Value &value_) : value(value_) {}
};
}
template<typename A, typename B>
std::ostream &
operator<<(std::ostream &o, const NP::Comma<A,B> &comma) {
return o << comma.first << ", " << comma.second;
}
template<typename T>
std::ostream &
operator<<(std::ostream &o, const NP::Assign<T> &assign) {
return o << T::name() << " = " << assign.value;
}
template<typename A, typename B>
NP::Comma<A,B>
operator,(const A &a, const B &b) {
return NP::Comma<A,B>(a,b);
}
#define NAMED_PARAM(type__, name__) \
struct NamedParam_##name__ { \
typedef NamedParam_##name__ This; \
typedef type__ Value; \
static const char *name() { return #name__; } /* used with bundle serialization */ \
NP::Assign<This> operator=(const Value &v) { return NP::Assign<This>(v); } \
} name__
namespace bar {
#define COMMA ,
NAMED_PARAM(pair<double COMMA double>, d);
//NAMED_PARAM(map<int COMMA double>, e);
template<typename Args>
void doo(const Args &args) {
pair<double,double> d_ = args[d];
cout << "bar:" << endl;
cout << "d = " << d_ << endl;
}
}
namespace foo {
NAMED_PARAM(const char *, a);
NAMED_PARAM(double, b);
NAMED_PARAM(string, c);
template<typename Args>
void doo(const Args &args) {
cout << args << endl;
const char *a_ = args[a];
double b_ = args[b];
string c_ = args[c];
cout << "foo:" << endl;
cout << "a = " << a_ << endl;
cout << "b = " << b_ << endl;
cout << "c = " << c_ << endl;
bar::doo(args);
}
}
int main() {
using namespace foo;
using namespace bar;
foo::doo((
a = "c-str",
b = 2,
c = "stl-str",
d = pair<double,double>(1.0, 2.0)
));
return 0;
}
Results:
a = c-str, b = 2, c = stl-str, d = (1, 2)
foo:
a = c-str
b = 2
c = stl-str
bar:
d = (1, 2)