|
Boost : |
Subject: [boost] [type_erasure] overloading macro
From: Christophe Henry (christophe.j.henry_at_[hidden])
Date: 2013-02-19 12:11:39
Hi all,
I played a bit more with overloading and it started being annoying and
error-prone to add more overloads of concept_map (with more arguments)
so I wrote a small macro to 1) generate my overloads and 2) save
myself the time reading compiler errors when I use
BOOST_TYPE_ERASURE_MEMBER and make a mistake in the number of
arguments.
It's for C++11 (argument pack) as it's all I need at the moment but I
suppose that with Boost.Preprocessor, it'd be for C++03 doable.
Well, in case it'd be of any use to someone, here it is, with a small
test (tested with g+ 4.5 with -std=c++0x).
#include <boost/type_erasure/concept_interface.hpp>
#include <boost/type_erasure/rebind_any.hpp>
#include <boost/type_erasure/derived.hpp>
#include <boost/type_erasure/is_placeholder.hpp>
#include <boost/type_erasure/constructible.hpp>
#include <boost/type_erasure/relaxed_match.hpp>
#include <boost/type_erasure/any.hpp>
#include <boost/type_erasure/builtin.hpp>
#include <boost/type_erasure/any_cast.hpp>
#include <boost/type_erasure/detail/macro.hpp>
#include <boost/mpl/vector.hpp>
#include <iostream>
#ifndef BOOST_NO_CXX11_VARIADIC_TEMPLATES
#define BOOST_TYPE_ERASURE_MEMBER_VARIADIC_I(qualname,concept_name,member)
\
BOOST_TYPE_ERASURE_OPEN_NAMESPACE(qualname)
\
template <typename T, typename... Args>
\
struct concept_name{
\
static void apply(const T& t, const Args... a) {
t.member(a...); } };
\
BOOST_TYPE_ERASURE_CLOSE_NAMESPACE(qualname)
\
namespace boost { namespace type_erasure {
\
template<class T, typename... U, class Base, class Enable>
\
struct concept_interface<
BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U... >, Base, T,
Enable> : Base { \
typedef void _fun_defined;
\
void member(typename rebind_any<Base, U>::type... arg)const
\
{call(BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U...>(),
*this, arg...);} };
\
template<class T, typename... U, class Base>
\
struct concept_interface<
BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U...>, Base, T,
typename Base::_fun_defined> : Base{ \
using Base::member; void member(typename rebind_any<Base, U
>::type... arg)const
\
{call(BOOST_TYPE_ERASURE_QUALIFIED_NAME(qualname)<T, U...>(),
*this, arg...);} };
\
}}
#endif
#define BOOST_TYPE_ERASURE_MEMBER_VARIADIC(qualified_name,member)
\
BOOST_TYPE_ERASURE_MEMBER_VARIADIC_I(
\
qualified_name,
\
BOOST_PP_SEQ_ELEM(BOOST_PP_DEC(BOOST_PP_SEQ_SIZE(qualified_name)),
qualified_name), \
member)
// supports overloading, does not require any number of arguments
BOOST_TYPE_ERASURE_MEMBER_VARIADIC((n1)(n2)(foo),foo)
namespace mpl = boost::mpl;
using namespace boost::type_erasure;
struct Test
{
void foo()const
{
std::cout << "foo() called" << std::endl;
}
void foo(int i)const
{
std::cout << "foo(int) called with: " << i << std::endl;
}
void foo(int i,char c)const
{
std::cout << "foo(int,char) called with: " << i << "," << c <<
std::endl;
}
void foo(double d)const
{
std::cout << "foo(double) called with: " << d << std::endl;
}
void foo(int i,double d)const
{
std::cout << "foo(int,double) called with: " << i << "," << d
<< std::endl;
}
void foo(int i,double d,char c)const
{
std::cout << "foo(int,double,char) called with: " << i << ","
<< d << "," << c << std::endl;
}
};
int main()
{
Test t;
any<
mpl::vector<
n1::n2::foo<_self>,
n1::n2::foo<_self, int>,
n1::n2::foo<_self, double>,
n1::n2::foo<_self, int, double>,
n1::n2::foo<_self, int, char>,
n1::n2::foo<_self, int, double, char>,
copy_constructible<>
>
> x (t);
x.foo(); // calls foo()
x.foo(1); // calls foo(int)
x.foo(1.0); // calls foo(double)
x.foo(1,1.0); // calls foo(int, double)
x.foo(1,'a'); // calls foo(int, char)
x.foo(1,1.0,'a'); // calls foo(int, double,char)
return 0;
}
Boost list run by bdawes at acm.org, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk