#include <type_traits>
#include <iostream>
namespace named {
struct param {};
template<class wantparam, class wanttype, class curparamname, class curparamtype, class...Rest,
class allowed=typename std::enable_if<!std::is_same<wantparam,typename std::decay<curparamname>::type>::value>::type
>
wanttype get(curparamname, curparamtype&&, Rest&&...rest)
{
static_assert(std::is_base_of<param,typename std::decay<curparamname>::type>::value,"value passed to named parameter list without a name");
static_assert(!std::is_base_of<param,typename std::decay<curparamtype>::type>::value,"name passed to named parameter list without a value");
return get<wantparam,wanttype>(rest...);
}
template<class wantparam, class wanttype, class curparamtype, class...Rest>
wanttype get(wantparam, curparamtype&& value, Rest&&...)
{
static_assert(std::is_base_of<param,typename std::decay<wantparam>::type>::value,"value passed to named parameter list without a name");
static_assert(!std::is_base_of<param,typename std::decay<curparamtype>::type>::value,"name passed to named parameter list without a value");
return std::forward<curparamtype>(value);
}
template<class wantparam, class wanttype, class curparamtype>
wanttype get(curparamtype)
{
static_assert(std::is_base_of<param,typename std::decay<curparamtype>::type>::value,"value passed to named parameter list without a name");
static_assert(!std::is_base_of<param,typename std::decay<curparamtype>::type>::value,"name passed to named parameter list without a value");
}
template<class wantparam, class wanttype>
wanttype get()
{static_assert(sizeof(wantparam)==0,"missing required named parameter");}
//add parameter names here. Make sure they all have unique types and inherit from param.
static struct a_type : public param{} a;
static struct b_type : public param{} b;
static struct c_type : public param{} c;
}
void my_func(int a, int b = 0, int c = 0){
std::cout << a << ' ' << b << ' ' << c << '\n';
}
template<class curparamname, class...Rest,
class allowed=typename std::enable_if<std::is_base_of<named::param,typename std::decay<curparamname>::type>::value>::type
>
void my_func(curparamname p, Rest...rest) {
return my_func(
named::get<named::a_type,int>(p, rest...),
named::get<named::b_type,int>(p, rest..., named::b, 0),
named::get<named::c_type,int>(p, rest..., named::c, 0)
);
}
int main() {
my_func(3);
my_func(3, 4);
my_func(3, 4, 5);
my_func(named::c, 6, named::a, 7);
//my_func(named::b, 8); //error C2338: missing required named parameter
my_func(named::c, 9, named::b, 10, named::a, 11);
//my_func(named::c, 12, 13, named::a, 14); //error C2338: value passed to named parameter list without a name
//my_func(named::c, named::a, 15); //error C2338: named passed to named parameter list without a value
return 0;
}
I2luY2x1ZGUgPHR5cGVfdHJhaXRzPgojaW5jbHVkZSA8aW9zdHJlYW0+CgpuYW1lc3BhY2UgbmFtZWQgewogICAgc3RydWN0IHBhcmFtIHt9OwogICAgCiAgICB0ZW1wbGF0ZTxjbGFzcyB3YW50cGFyYW0sIGNsYXNzIHdhbnR0eXBlLCBjbGFzcyBjdXJwYXJhbW5hbWUsIGNsYXNzIGN1cnBhcmFtdHlwZSwgY2xhc3MuLi5SZXN0LCAKICAgICAgICBjbGFzcyBhbGxvd2VkPXR5cGVuYW1lIHN0ZDo6ZW5hYmxlX2lmPCFzdGQ6OmlzX3NhbWU8d2FudHBhcmFtLHR5cGVuYW1lIHN0ZDo6ZGVjYXk8Y3VycGFyYW1uYW1lPjo6dHlwZT46OnZhbHVlPjo6dHlwZQogICAgPgogICAgd2FudHR5cGUgZ2V0KGN1cnBhcmFtbmFtZSwgY3VycGFyYW10eXBlJiYsIFJlc3QmJi4uLnJlc3QpIAogICAgewogICAgICAgIHN0YXRpY19hc3NlcnQoc3RkOjppc19iYXNlX29mPHBhcmFtLHR5cGVuYW1lIHN0ZDo6ZGVjYXk8Y3VycGFyYW1uYW1lPjo6dHlwZT46OnZhbHVlLCJ2YWx1ZSBwYXNzZWQgdG8gbmFtZWQgcGFyYW1ldGVyIGxpc3Qgd2l0aG91dCBhIG5hbWUiKTsKICAgICAgICBzdGF0aWNfYXNzZXJ0KCFzdGQ6OmlzX2Jhc2Vfb2Y8cGFyYW0sdHlwZW5hbWUgc3RkOjpkZWNheTxjdXJwYXJhbXR5cGU+Ojp0eXBlPjo6dmFsdWUsIm5hbWUgcGFzc2VkIHRvIG5hbWVkIHBhcmFtZXRlciBsaXN0IHdpdGhvdXQgYSB2YWx1ZSIpOwogICAgICAgIHJldHVybiBnZXQ8d2FudHBhcmFtLHdhbnR0eXBlPihyZXN0Li4uKTsKICAgIH0KICAgIAogICAgdGVtcGxhdGU8Y2xhc3Mgd2FudHBhcmFtLCBjbGFzcyB3YW50dHlwZSwgY2xhc3MgY3VycGFyYW10eXBlLCBjbGFzcy4uLlJlc3Q+CiAgICB3YW50dHlwZSBnZXQod2FudHBhcmFtLCBjdXJwYXJhbXR5cGUmJiB2YWx1ZSwgUmVzdCYmLi4uKSAKICAgIHsKICAgICAgICBzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfYmFzZV9vZjxwYXJhbSx0eXBlbmFtZSBzdGQ6OmRlY2F5PHdhbnRwYXJhbT46OnR5cGU+Ojp2YWx1ZSwidmFsdWUgcGFzc2VkIHRvIG5hbWVkIHBhcmFtZXRlciBsaXN0IHdpdGhvdXQgYSBuYW1lIik7CiAgICAgICAgc3RhdGljX2Fzc2VydCghc3RkOjppc19iYXNlX29mPHBhcmFtLHR5cGVuYW1lIHN0ZDo6ZGVjYXk8Y3VycGFyYW10eXBlPjo6dHlwZT46OnZhbHVlLCJuYW1lIHBhc3NlZCB0byBuYW1lZCBwYXJhbWV0ZXIgbGlzdCB3aXRob3V0IGEgdmFsdWUiKTsKICAgICAgICByZXR1cm4gc3RkOjpmb3J3YXJkPGN1cnBhcmFtdHlwZT4odmFsdWUpOwogICAgfQogICAgCiAgICB0ZW1wbGF0ZTxjbGFzcyB3YW50cGFyYW0sIGNsYXNzIHdhbnR0eXBlLCBjbGFzcyBjdXJwYXJhbXR5cGU+CiAgICB3YW50dHlwZSBnZXQoY3VycGFyYW10eXBlKSAKICAgIHsKICAgICAgICBzdGF0aWNfYXNzZXJ0KHN0ZDo6aXNfYmFzZV9vZjxwYXJhbSx0eXBlbmFtZSBzdGQ6OmRlY2F5PGN1cnBhcmFtdHlwZT46OnR5cGU+Ojp2YWx1ZSwidmFsdWUgcGFzc2VkIHRvIG5hbWVkIHBhcmFtZXRlciBsaXN0IHdpdGhvdXQgYSBuYW1lIik7CiAgICAgICAgc3RhdGljX2Fzc2VydCghc3RkOjppc19iYXNlX29mPHBhcmFtLHR5cGVuYW1lIHN0ZDo6ZGVjYXk8Y3VycGFyYW10eXBlPjo6dHlwZT46OnZhbHVlLCJuYW1lIHBhc3NlZCB0byBuYW1lZCBwYXJhbWV0ZXIgbGlzdCB3aXRob3V0IGEgdmFsdWUiKTsKICAgIH0KICAgIAogICAgdGVtcGxhdGU8Y2xhc3Mgd2FudHBhcmFtLCBjbGFzcyB3YW50dHlwZT4KICAgIHdhbnR0eXBlIGdldCgpIAogICAge3N0YXRpY19hc3NlcnQoc2l6ZW9mKHdhbnRwYXJhbSk9PTAsIm1pc3NpbmcgcmVxdWlyZWQgbmFtZWQgcGFyYW1ldGVyIik7fQoKCiAgICAvL2FkZCBwYXJhbWV0ZXIgbmFtZXMgaGVyZS4gIE1ha2Ugc3VyZSB0aGV5IGFsbCBoYXZlIHVuaXF1ZSB0eXBlcyBhbmQgaW5oZXJpdCBmcm9tIHBhcmFtLgogICAgc3RhdGljIHN0cnVjdCBhX3R5cGUgOiBwdWJsaWMgcGFyYW17fSBhOwogICAgc3RhdGljIHN0cnVjdCBiX3R5cGUgOiBwdWJsaWMgcGFyYW17fSBiOwogICAgc3RhdGljIHN0cnVjdCBjX3R5cGUgOiBwdWJsaWMgcGFyYW17fSBjOwp9Cgp2b2lkIG15X2Z1bmMoaW50IGEsIGludCBiID0gMCwgaW50IGMgPSAwKXsKICAgIHN0ZDo6Y291dCA8PCBhIDw8ICcgJyA8PCBiIDw8ICcgJyA8PCBjIDw8ICdcbic7Cn0KCnRlbXBsYXRlPGNsYXNzIGN1cnBhcmFtbmFtZSwgY2xhc3MuLi5SZXN0LCAKICAgIGNsYXNzIGFsbG93ZWQ9dHlwZW5hbWUgc3RkOjplbmFibGVfaWY8c3RkOjppc19iYXNlX29mPG5hbWVkOjpwYXJhbSx0eXBlbmFtZSBzdGQ6OmRlY2F5PGN1cnBhcmFtbmFtZT46OnR5cGU+Ojp2YWx1ZT46OnR5cGUKPgp2b2lkIG15X2Z1bmMoY3VycGFyYW1uYW1lIHAsIFJlc3QuLi5yZXN0KSB7CiAgICByZXR1cm4gbXlfZnVuYygKICAgICAgICBuYW1lZDo6Z2V0PG5hbWVkOjphX3R5cGUsaW50PihwLCByZXN0Li4uKSwKICAgICAgICBuYW1lZDo6Z2V0PG5hbWVkOjpiX3R5cGUsaW50PihwLCByZXN0Li4uLCBuYW1lZDo6YiwgMCksCiAgICAgICAgbmFtZWQ6OmdldDxuYW1lZDo6Y190eXBlLGludD4ocCwgcmVzdC4uLiwgbmFtZWQ6OmMsIDApCiAgICAgICAgKTsKfQoKaW50IG1haW4oKSB7CiAgICBteV9mdW5jKDMpOwogICAgbXlfZnVuYygzLCA0KTsKICAgIG15X2Z1bmMoMywgNCwgNSk7CiAgICBteV9mdW5jKG5hbWVkOjpjLCA2LCBuYW1lZDo6YSwgNyk7CiAgICAvL215X2Z1bmMobmFtZWQ6OmIsIDgpOyAvL2Vycm9yIEMyMzM4OiBtaXNzaW5nIHJlcXVpcmVkIG5hbWVkIHBhcmFtZXRlcgogICAgbXlfZnVuYyhuYW1lZDo6YywgOSwgbmFtZWQ6OmIsIDEwLCBuYW1lZDo6YSwgMTEpOwogICAgLy9teV9mdW5jKG5hbWVkOjpjLCAxMiwgMTMsIG5hbWVkOjphLCAxNCk7IC8vZXJyb3IgQzIzMzg6IHZhbHVlIHBhc3NlZCB0byBuYW1lZCBwYXJhbWV0ZXIgbGlzdCB3aXRob3V0IGEgbmFtZQogICAgLy9teV9mdW5jKG5hbWVkOjpjLCBuYW1lZDo6YSwgMTUpOyAvL2Vycm9yIEMyMzM4OiBuYW1lZCBwYXNzZWQgdG8gbmFtZWQgcGFyYW1ldGVyIGxpc3Qgd2l0aG91dCBhIHZhbHVlCiAgICByZXR1cm4gMDsKfQ==