1
votes

Static array initialization... with const pointers... to overloaded, templatized member functions. Is there a way it can be done (C++03 standard code)? I mean, if I have the template class


template <class T1, class U1, typename R1>
class Some_class {
public:
    typedef T1 T;
    typedef U1 U;
    typedef R1 R;

    R operator()(T& v) { /* dereference pointer to a derived class (U),
                            overloaded member function (U::f) */ };

private:
    static R (U::* const pmfi[/* # of overloaded functions in U */])(T&);
};

Used as

template <class BASE, typename RET>
class Other_class : public Some_class<BASE, Other_class<BASE, RET>, RET> {
    RET f(/* type derived from BASE */) {}
    RET f(/* other type derived from BASE */) {}
    RET f(/* another type derived from BASE */) {}
    ...
};

Question: how can I initialize de array pmfi (no typedefs, please)?

Notes:
1. As a static array MUST be initialized at file scope, template parameters and pmfi must be full qualified (the only way I know to access template parameters outside a class scope is to typedef them...).
2. So far so good. No problems with the compiler (Comeau 4.3.10.1). Problems start popping up when I try to fullfill the initializer list { ... }.
2.1. The compiler complains the template argument list is missing, no matter what I do.
2.2. I have no idea how to select the correct overloaded U::f function.

BTW, this is a kind of "jump table" generator from a boost.preprocessor list. The code I am trying to implement is of course much more complex then this one, but this is his essence.

Thanks for any help

1

1 Answers

1
votes

To use BOOST_PP_ENUM in the way that you've shown, you would need a macro that takes a 'number' and yields an expression that is the address of an appropriate member of the appropriate class. I don't see a good way to do this without an explicit list unless the desired functions all have manufactured names (e.g. memfun1, memfun2, etc.). Except in the case, it's going to be easier to list the function address expressions explicitly that to used BOOST_PP_ENUM.

You are using identifiers in this array that are the same as the template parameters in Some_class.

R (U::* const pmfi[])(T&) = { /* ... */ }

Is this really supposed to be the templated member of Some_class?

template< class T, class U, class R >
R (U::* const Some_class<T, U, R>::pmfi[])(T&) = { /* ... */ }

If so, is the same instantiation going to work with all combinations of types that you are going to us the template Some_class with? If so, you have a very constrained set of classes, perhaps you can do away with the template. If not, you are going to have to specialize Some_class for every combination of template parameters in which case the template is not gaining you very much.

Edit, post edit: If I've understood you correctly then you can't do what you've suggested because the array of pointers must be of exactly the right signature.

Reducing it to a simple function pointer example, you can't do this:

void f(Derived&);

void (*p)(Base&) = &f;

otherwise, it would subvert type safety:

OtherDerived od; // derived from Base, but no from Derived

 // I've managed to pass something that isn't a Derived reference to f
 // without an explicit (and dangerous) cast
(*p)(od);

In your array of function pointers, the initializers must all be to functions of the right signature.