There two unrelated structures A and B
template <typename T>
struct A {};
template <typename T>
struct B {};
one enum type
typedef enum { ma, mb} M;
and class C containing function templates
class C
{
public:
template <typename T>
static void f1 ( A <T> &a) {}
template <typename T>
static void f2 ( B <T> &b) {}
template <typename U>
static void algo (U &u, M m)
{
/*Long algorithm here
....
*/
if ( m == ma) f1(u);
else f2(u);
}
};
Static method algo contains some algorithm, that is quite difficult… It modified some values and results into structure A or B.
I would like to run static method algo with objects A or B depending on M value. But how to say it to my compiler 🙂
int main()
{
A <double> a;
C::algo (a, ma); //Error
}
Error 1 error C2784: 'void C::f1(A<T>)' : could not deduce template argument for 'A<T>' from 'B<T>
A] I was thinking about pointer to function, but they are not usable with function templates.
B] Maybe a compile polymorphism could help
template <typename U, M m>
static void algo (U &u, M <m> ) { ...} //Common for ma
template <typename U, M m>
static void algo (U &u, M <mb> ) { ...} //Spec. for mb
But this solution has one big problem: Both implementations should unnecessarily include almost the same code (why to write the algorithm twice?).
So I need one function algo() processing both types of arguments A and B. Is there any more comfortable solution?
It seems that you are using the enum to convey type information from the user. I would suggest that you don’t.
In the simplest case if
f1andf2are renamedf, then you can remove theifaltogether and just call it. The compiler will call the appropriate overload for you.If you cannot or don’t want to rename the function templates, then you can write a helper template that will dispatch for you (basic class template undefined, specialisations for
AandBthat dispatch to the appropriate static function)If the enum is used for something else (that the compiler cannot resolve for you), you can still pass it around and rewrite the helper to dispatch on the enum rather than the type of the argument and you will have to rewrite the code to have the enum value as a compile time constant (simplest: pass it as template argument to
algo). In this case ou can write function specialisations instead of classes if you want, as they would be full specialisations. But note that if you can avoid having to pass it you will remove a whole family of errors: passing the wrong enum value.For the other alternatives, it is easier if the enclosing scope is a namespace, but the idea would be the same (just might need to fight the syntax a bit harder:
Again, getting this to work with a class might be a bit trickier as it will probably need a couple of forward declarations, and I don’t have a compiler at hand, but the sketch should lead you in the right direction.