|
|
|
|
||||||
![]() |
|
|
LinkBack | Outils de la discussion |
|
|
#1 |
|
Messages: n/a
Hébergeur: |
Hello,
I couldn't figure out how to specialize the following member template: #include <iostream> template <typename T1> class sample { T1 value; public: sample(T1 v) : value(v) {} template <typename T2> T1 val(T2 arg); }; template <typename T1> template <typename T2> T1 sample<T1>::val(T2 arg) { return arg + value; } template <typename T1> template <> T1 sample<T1>::val(char arg) { return arg + value; } int main() { sample<int> s(0); char c = 'a'; int i = 10; std ::cout << s.val(c) << std::endl; std::cout << s.val(i) << std::endl; return 0; } I only want to partial specialize with T2 = char. Above gives error "enclosing class templates are not explicitly specialized" How do I fix this? Thanks. Mark |
|
|
|
#2 |
|
Messages: n/a
Hébergeur: |
On Feb 7, 5:34 pm, mark....@gmail.com wrote:
> Hello, > > I couldn't figure out how to specialize the following member template: > > #include <iostream> > template <typename T1> class sample { > T1 value; > > public: > sample(T1 v) : value(v) {} > template <typename T2> T1 val(T2 arg); > > }; > > template <typename T1> template <typename T2> T1 sample<T1>::val(T2 arg) > { > return arg + value; > > } > > template <typename T1> template <> T1 sample<T1>::val(char arg) > { > return arg + value; > > } > > int main() > { > sample<int> s(0); > char c = 'a'; > int i = 10; > std ::cout << s.val(c) << std::endl; > std::cout << s.val(i) << std::endl; > return 0; > > } > > I only want to partial specialize with T2 = char. Above gives error > "enclosing class templates are not explicitly specialized" > > How do I fix this? Thanks. > > Mark You can't explicitly specialize a class or member template unless its enclosing class templates are also explicitly specialized. |
|
|
|
#3 |
|
Messages: n/a
Hébergeur: |
pastbin@gmail.com wrote:
> On Feb 7, 5:34 pm, mark....@gmail.com wrote: >> Hello, >> >> I couldn't figure out how to specialize the following member template: >> >> #include <iostream> >> template <typename T1> class sample { >> T1 value; >> >> public: >> sample(T1 v) : value(v) {} >> template <typename T2> T1 val(T2 arg); >> >> }; >> >> template <typename T1> template <typename T2> T1 sample<T1>::val(T2 arg) >> { >> return arg + value; >> >> } >> >> template <typename T1> template <> T1 sample<T1>::val(char arg) >> { >> return arg + value; >> >> } >> >> int main() >> { >> sample<int> s(0); >> char c = 'a'; >> int i = 10; >> std ::cout << s.val(c) << std::endl; >> std::cout << s.val(i) << std::endl; >> return 0; >> >> } >> >> I only want to partial specialize with T2 = char. Above gives error >> "enclosing class templates are not explicitly specialized" >> >> How do I fix this? Thanks. >> >> Mark > > You can't explicitly specialize a class or member template unless its > enclosing class templates are also explicitly specialized. So are you saying I have to specialized T1 to make it work? |
|
|
|
#4 |
|
Messages: n/a
Hébergeur: |
On Feb 7, 6:06 pm, mark....@gmail.com wrote:
> > So are you saying I have to specialized T1 to make it work? Yes. It could be: template <> template <> int sample<int>::val<char>(char arg) { return arg + value; } |
|
|
|
#5 |
|
Messages: n/a
Hébergeur: |
>> So are you saying I have to specialized T1 to make it work?
You can implement val() by delegation to an overloaded function or a function of a er template that takes the two template parameters T1 and T2 and is partially specialized as appropriate. -- Marek |
|
|
|
#6 |
|
Messages: n/a
Hébergeur: |
mark.mac@gmail.com wrote:
> ... > I couldn't figure out how to specialize the following member template: > > #include <iostream> > template <typename T1> class sample { > T1 value; > > public: > sample(T1 v) : value(v) {} > template <typename T2> T1 val(T2 arg); > }; > > template <typename T1> template <typename T2> T1 sample<T1>::val(T2 arg) > { > return arg + value; > } > > template <typename T1> template <> T1 sample<T1>::val(char arg) > { > return arg + value; > } > ... > I only want to partial specialize with T2 = char. Above gives error > "enclosing class templates are not explicitly specialized" > > How do I fix this? Thanks. In C++ for some reason explicit specialization of member templates is only allowed when the enclosing class template is also explicitly specialized. For example, the following code is ill-formed for exactly that reason template<typename T> struct A { template<typename U> struct B { int i; }; template<> struct B<int> { int j; }; // <- ERROR }; With class templates there's an [ugly] workaround: partial specialization of member templates are perfectly OK, even without specializing the enclosing class, so the above can be turned into a partial specialization by introducing a dummy parameter template<typename T> struct A { template<typename U, typename DUMMY = void> struct B { int i; }; template<typename DUMMY> struct B<int, DUMMY> { int i; }; // <- OK }; ... A<void>::B<char> bc; A<void>::B<int> bi; bc.i = 4; bi.j = 2; It is not exactly the same thing, but it s in many cases (which makes the aforementioned restriction on explicit specialization look even more illogical). In your case though we are dealing with a member function template, not a member class template. Function templates don't support partial specialization, which means that we can't use the above workaround. However, I think you can achieve [almost?] what you want by using a different C++ mechanism - function overloading. Just supply an overloaded version of your function with 'char' argument and you should be OK. Of course, you'll have to add its declaration to the template class definition template<typename T1> class sample { T1 value; public: sample(T1 v) : value(v) {} template<typename T2> T1 val(T2 arg); T1 val(char arg); }; template<typename T1> template<typename T2> T1 sample<T1>::val(T2 arg) { return arg + value; } template<typename T1> T1 sample<T1>::val(char arg) { return arg + value; } In contexts when member template arguments are not specified, the compiler will select the overloaded function. sample<int> s; s.val('c'); // calls the overloaded 'char' version But keep in mind that when the template arguments are specified explicitly (or a mere '<>' is used), the template version will be chosen s.val<>('c'); // instantiates and calls the template version s.val<char>('c'); // instantiates and calls the template version In this respect it is different from explicit specialization. I don't know whether this matters in your case. -- Best regards, Andrey Tarasevich |
|
|
|
#7 |
|
Messages: n/a
Hébergeur: |
Andrey Tarasevich wrote:
> ... > With class templates there's an [ugly] workaround: partial > specialization of member templates are perfectly OK, even without > specializing the enclosing class, so the above can be turned into a > partial specialization by introducing a dummy parameter > > template<typename T> struct A { > template<typename U, typename DUMMY = void> struct B { int i; }; > template<typename DUMMY> struct B<int, DUMMY> { int i; }; // <- OK > }; Sorry for the typo. Should be ... template<typename DUMMY> struct B<int, DUMMY> { int j; }; // <- OK ... -- Best regards, Andrey Tarasevich |
|
|
|
#8 |
|
Messages: n/a
Hébergeur: |
Andrey Tarasevich wrote:
[snip] > > In your case though we are dealing with a member function template, not > a member class template. Function templates don't support partial > specialization, which means that we can't use the above workaround. > However, I think you can achieve [almost?] what you want by using a > different C++ mechanism - function overloading. Just supply an > overloaded version of your function with 'char' argument and you should > be OK. Of course, you'll have to add its declaration to the template > class definition Yes, that's what I did, thanks for your time. Mark |
|
![]() |
| Outils de la discussion | |
|
|