On Fri, 23 Apr 2010, John Dlugosz wrote:
I tried something like this: First, the general form in one header known by everything:
template
dim_s foo (const T1& left, const T2& right); Then, in a header that gets more concrete, provide its own form that is meant to be used when objects of those types are involved:
template
typename enable_if_c< is_base_of ::value && is_base_of ::value, dim_s>::type foo (const T1& left, const T2& right); Here, the template defined in this header derives from genericbase, so I have a hook to say "all types derived from any specialization of this template".
Now, this actually causes an ambiguity. The latter is not a specialization but a peer overloading, and when both are present, both are templates that form exact matches and template arguments at the least restrictive way to refer to the type.
This function is already internal plumbing, so I don't mind it being a little messy to use. What I'm really doing is multimethod dispatch: various concrete classes, generic versions for making such, and special combinations all have their own efficient logic, with a fallback (slow) that always works. And I want all the plumbing to disappear at compile time so it efficiently calls the efficient function. So if I'm really guilty of the "X for Y" problem, that is what I'm really trying to do, and if there are any suggestions on doing that better in general, please let'em rip.
Have you seen URL:http://www.codeproject.com/KB/recipes/mmcppfcs.aspx?
As for the road I'm on now, the simplest thing is to somehow give each form a priority. I did that by adding a 3rd parameter. The general form declares a void*, and the specialized form declares an int. The caller always gives a zero. I'm wondering what is the longest chain of different priorities I can use with this method, using only compiler primitive types that the optimizer should be able to toss when the function is inlined. I know I could use dummy classes with any number of derivations, but I'm thinking I can get several levels just using primitive types. Any suggestions?
What about (... is for you to fill in): template <..., typename X> // Priority 0 void foo(..., X); template <..., typename X> // Priority 1 void foo(..., X*); template <..., typename X> // Priority 2 void foo(..., X**); Then call foo(..., (void*******************)0) (for however many priority levels you want to allow). Perhaps you can even use a default argument to fill in the value in C++0x, but I'm not sure about that. You can of course write a wrapper function that adds in the dummy last argument. -- Jeremiah Willcock