Reducing the pattern when decorating

I have a large number of classes that are used to decorate several specific methods.

Is there a clean way to reduce the amount of template code (basically, all the constructor and member parameters for storing them) that need to be added to each of these classes? Or, even better, is there a better way to do this?

I cannot use virtual methods and can only use a subset of the C ++ 11 functions supported by gcc 4.6 and vs2010.

I believe that C ++ 11 inherits constructors, but none of them support them, and I don't know about a workaround.

Here is an example of what these classes look like:

template<class Underlying, class T1>
struct A : Base<A<Underlying, T1> >
{
    typedef AImpl<decltype(declval<Underlying>().foo()), T1> impl;
    A(Underlying u, T1 t1) :
        u_(u),
        t1_(t1)
    {}

    impl foo() const { return impl(u_.foo(), t1_); }
    impl bar() const { return impl(u_.bar(), t1_); }

    const Underlying u_;
    T1 t1_;
};


template<class Underlying, class T1, class T2>
struct B : Base<B<Underlying, T1, T2> >
{
    typedef BImpl<decltype(declval<Underlying>().bar()), T1, T2> impl;
    B(Underlying u, T1 t1, T2 t2) :
        u_(u),
        t1_(t1),
        t2_(t2)
    {}

    impl foo() const { return impl(u_.bar(), 999, t2_); }
    impl bar() const { return impl(u_.foo(), t1_, t2_); }

    const Underlying u_;
    T1 t1_;
    T2 t2;
};
+5
source share
2 answers

GCC 4.6.

template<class Underlying, class... T>
struct B : Base<B<Underlying, T...>>
{
    typedef BImpl<decltype(declval<Underlying>().bar()), T...> impl;

    template<typename V...>
    B(Underlying u, V... v) :
        u_(u),
        t_(std::forward<V>(v)...)
    {}

    impl foo() const { return impl(u_.bar(), 999, std::get<1>(t_)); } // Not sure what the 999 is?
    impl bar() const { return impl(u_.foo(), std::get<0>(t_), std::get<1>(t_)); }

    const Underlying u_;
    std::tuple<T...> t_;
};
+1

vs2010, Boost.Preprocessor. , , 3 256, ++ 11 . , , , ( ++ 11 Boost.Preprocessor ):

#define FORWARD(z, n, data) \
    ::std::forward<BOOST_PP_CAT(BOOST_PP_TUPLE_ELEM(2, 0, data), n)> \
    (BOOST_PP_CAT(BOST_PP_TUPLE_ELEM(2, 1, data), n)) \
    /**/

//------------------------------------------------------------------------
// template<class R, class... A>
// ::std::function<R(A...)> decorate(::std::function<R(A...)> const& func)
// {
//     return [func](A&&... a) -> R
//     {
//         /* DECORATOR STUFF */
//         return func(::std::forward<A>(a)...);
//     };
// }
//------------------------------------------------------------------------
#define MACRO(z, n, _) \
    template<class R BOOST_PP_ENUM_TRAILING_PARAMS_Z(z, n, class A)> \
    ::std::function<R(BOOST_PP_ENUM_PARAMS_Z(z, n, a)> \
        decorate(::std::function<R(BOOST_PP_ENUM_PARAMS_Z(z, n, A))> const& func) \
    { \
        return [func](BOOST_PP_ENUM_BINARY_PARAMS_Z(z, n, A, &&a)) -> R \
        { \
            /* DECORATOR STUFF */ \
            return func(BOOST_PP_ENUM_ ## z(n, FORWARD, (A, a))); \
        }; \
    } \
    /**/

BOOST_PP_REPEAT(10, MACRO, ~)

#undef MACRO
#undef FORWARD

, std:: bind - , . , lambdas, (, lambdas, , offs) bind (, - ).

+1

All Articles