Boost logo

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