Conundrum Template

I came across a C ++ pattern. I tried to cut it to a minimum, and now I'm not even sure that what I'm trying to do is possible. Take a look at the following code (in some kind of .h file).

template<typename T> class A { public: template<typename S> void f(S x); }; class B1 { }; template<typename S> class B2 { }; //This one works: template<> template<typename S> void A<B1>::f(S x) { } //This one does not work: template<> template<typename S> void A<B2<S>>::f(S x) { } 

In my main function, I have something like this:

 //This one works: A<B1> first; first.f<int>(5); //This one does not work: A<B2<int>> second; second.f<int>(5); 

The error message I get due to the second part,

 error C3860: template argument list following class template name must list parameters in the order used in template parameter list error C3855: 'A<T>': template parameter 'T' is incompatible with the declaration 

Any idea what the problem is?


Edit

To make the problem more specific, here is my motivation. I want the function f above to have specializations for T=std::tuple<T1, T2> , T=std::tuple<T1, T2, T3> and T=std::tuple<T1, T2, T3, T4> where the types in tuple are still not connected.

+4
source share
3 answers

You are trying to partially specialize a member function template. This is impossible, I'm afraid ...

+4
source

There are two problems in your code. Firstly, the second specialization is illegal because

 template<> // parameters useable for the specialization of A you refer to // since it is a function, no partial specialization is allowed. template<typename S> // parameters for the function parameters void A<B2<S>> // S can not be used here! ::f(S x) // only here { } 

If I changed it to

 template<> template<typename S> void A<B2<int>>::f(S x) { } 

it works, and now the second problem opens:

 second.f<B2<int>>(5); 

This sets S to B2<int> , and the function expects the parameter S x - but the integer 5 cannot be converted to this type. Change it to:

 B2<int> x; second.f<B2<int>>(x); 

and it also works.

Please note that this may not solve the problem you are trying to solve, it just explains what is happening.


Thinking of your editing: I think that the fact that you are trying to specialize in T=std::tuple<...> already indicates the direction: T is a parameter of template A , and that is what you should specialize. Maybe something like:

 template< typename T > class F // used to implement f(), so you can specialize // just F/f() instead of the whole class A { void f(T x) { /* default impl */ } }; template< typename T1, typename T2 > class F< std::tuple< T1, T2 > > { void f(T1 x, T2 y) { /* special impl */ } }; template< typename T > class A : public F< T > { // ...other stuff... }; 
+3
source

If you want to pass another template to the template, you must use the template template options , so your template A <will look like this:

 template<typename T> class A { public: template<template <typename> class H, typename S> void f(H<S> x); }; 

Now you can transfer the template to your template.

I do not think that you can specialize in template template parameters if your original template did not use this type of parameter.

+1
source