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
{
virtual void operator()(S s) = 0;
}
template
{
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
{
void operator()(S s, W w);
}
template<typename S>
class derived : public baseclass
{
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 class pre_base; // common thing interface elements
template class base : public pre_base // general thing
interface
template<S> class base : public pre_base // thing
interface with no W
...
// a thing_list is a compound thing (exposes a thing interface)
template thing_list_base : public base // common
implementation for a list of things
template thing_list : public thing_list_base // general
impl. for list of general things
template <S> thing_list : public thing_list_base //
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
{
void operator()(S);
};
template ,
public baseclass
{
// 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
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
class foo { void operator()(S, W); }; template <typename S> class foo
{ void operator()(S); };template
class derived: public foo , public baseclass{ // 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