generic programming : variadic virtual function

I'm finally doing something nontrivial with templates and I've painted myself into an interesting corner. boost::enable_if looks like it might be a solution but I've not made it work yet. extracting the essence of the situation: template<typename S, typename W> class baseclass { virtual void operator()(S s, W w) = 0; } template<typename S> class baseclass<S,void> { virtual void operator()(S s) = 0; } template<typename S, typename W = void> class derived : public baseclass<S,W> { void operator()(S s); // if W is void void operator()(S s, W w); // otherwise } How can I make this work? MSVC9, if that makes a difference. I tried adapting some examples from the enable_if documentation but that led to wandering around aimlessly making random changes to the text. TIA, -swn

Wouldn't the following give the desired result? template<typename S, typename W> class derived : public baseclass<S,W> { void operator()(S s, W w); } template<typename S> class derived<S, void> : public baseclass<S,void> { void operator()(S s); } Regards Bruno

From: Bruno Lalande [mailto:bruno.lalande@gmail.com] Wouldn't the following give the desired result?
Yes, in fact after I found no answers in my mailbox this morning I noodled on the problem some more and came up with that solution. The difficulty is that there is a lot of non-variadic cruft common to the general and specialized template classes. I didn't want to repeat all of that. My solution was to insert a new intermediate template class in the hierarchy. But that would scale poorly if there were a richer set of variadic member enabling conditions. And maintaining extra layers of forwarding constructor definitions can be tedious and error-prone. Oh well, one can't have everything. To summarize the issue: boost::enable_if does not seem to work for selectively declaring member function signatures so if you have members with signatures that vary in a complex way depending on template parameters you have to use class template specialization. To avoid repeating non-variadic member declarations, factor them into a common public base class. Here's my class hierarchy now: template<S,W> class pre_base; // common thing interface elements template<S,W=void> class base : public pre_base<S,W> // general thing interface template<S> class base<S,void> : public pre_base<S,void> // thing interface with no W ... // a thing_list is a compound thing (exposes a thing interface) template <S,W> thing_list_base : public base<S,W> // common implementation for a list of things template <S,W=void> thing_list : public thing_list_base<S,W> // general impl. for list of general things template <S> thing_list<S,void> : public thing_list_base<S,void> // impl. for list of things w/o Ws. The repeated specialization pattern is what I was missing; the concrete class template and the interface templates use the same pattern. I had the interface declarations in place but was struggling with the concrete class templates. Thank you! -swn

Yes, in fact after I found no answers in my mailbox this morning I noodled on the problem some more and came up with that solution. The difficulty is that there is a lot of non-variadic cruft common to the general and specialized template classes. I didn't want to repeat all of that.
Another way to solve that could be to isolate the variadic stuff if a class (named "foo" below): template <typename S, typename W> class foo { void operator()(S, W); }; template <typename S> class foo<S, void> { void operator()(S); }; template <typename S, typename W> class derived: public foo<S, W>, public baseclass<S, W> { // common non-variadic stuff }; If I remember the C++ rules well, the operator() in "foo" would properly override the virtual operator() of "baseclass" in "derived". You can use a CRTP if "foo" needs anything in "derived" for its implementation... Bruno

On Thu, Aug 27, 2009 at 6:04 AM, Bruno Lalande<bruno.lalande@gmail.com> wrote:
Yes, in fact after I found no answers in my mailbox this morning I noodled on the problem some more and came up with that solution. The difficulty is that there is a lot of non-variadic cruft common to the general and specialized template classes. I didn't want to repeat all of that.
Another way to solve that could be to isolate the variadic stuff if a class (named "foo" below):
template <typename S, typename W> class foo { void operator()(S, W); };
template <typename S> class foo<S, void> { void operator()(S); };
template <typename S, typename W> class derived: public foo<S, W>, public baseclass<S, W> { // common non-variadic stuff };
If I remember the C++ rules well, the operator() in "foo" would properly override the virtual operator() of "baseclass" in "derived".
You can use a CRTP if "foo" needs anything in "derived" for its implementation...
I actually had a rather identical problem as the first post, but I solved it rather easily using Boost.Fusion building up a helper struct to act as the operator().
participants (3)
-
Bruno Lalande
-
OvermindDL1
-
Stephen Nuchia