Question about (problem with) template specialization

M

michael.young

I have a situation where I need to specialize a class template that
has two template parameters. Unfortunately, it needs to be
specialized for multiple cases, and, in one case, it leads to a
"conflict" - i.e., the specialization to be used is ambiguous. No
problem - since the one case specializes for the first parameter and
the other case specializes the second, I figured I could just provide
a third specialization for both parameters that covers that particular
case. Unfortunately, I'm getting errors to the effect that this
explicit specialization is not allowed. (I used the Borland C++
Builder 2006 compiler, but then I checked it using the online Comeau C+
+ compiler, which also yielded a similar error.) Can anyone explain
what I'm doing wrong? Any help would be greatly appreciated.
The code is pasted at the bottom of this message, after the diagnostic
message from the Comeau compiler.
Thanks,
Michael

Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 79: error: "const TestPOD<int, char>
&TestPOD<int,
char>::eek:perator=(const int &)" is not an entity that can be
explicitly specialized
TestPOD< int, char >::eek:perator= ( const int& source_value )
^

1 error detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed

//********* CODE STARTS HERE *************

#include <iostream>

template < typename T1, typename T2 >
struct TestPOD
{
const TestPOD< T1, T2 >&
operator= ( const T1& source_value ) ;

T1 value_ ;
} ;

template < typename T1, typename T2 >
const TestPOD< T1, T2 >&
TestPOD< T1, T2 >::eek:perator= ( const T1& source_value )
{
std::cout << "In non-specialized version..." << std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;
}
//
******************************************************************************
// Specialized : T1 = int

template < typename T2 >
struct TestPOD< int, T2 >
{
const TestPOD< int, T2 >&
operator= ( const int& source_value ) ;

int value_ ;
} ;

template < typename T2 >
const TestPOD< int, T2 >&
TestPOD< int, T2 >::eek:perator= ( const int& source_value )
{
std::cout << "In specialized version (T1 = int)..." << std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;
}

//
******************************************************************************
// Specialized : T2 = char

template < typename T1 >
struct TestPOD< T1, char >
{
const TestPOD< T1, char >&
operator= ( const T1& source_value ) ;

T1 value_ ;
} ;

template < typename T1 >
const TestPOD< T1, char >&
TestPOD< T1, char >::eek:perator= ( const T1& source_value )
{
std::cout << "In specialized version (T2 = char)..." << std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;
}

//
******************************************************************************
// Specialized : T1 = int, T2 = char

template < >
struct TestPOD< int, char >
{
const TestPOD< int, char >&
operator= ( const int& source_value ) ;

int value_ ;
} ;

template < >
const TestPOD< int, char >&
TestPOD< int, char >::eek:perator= ( const int& source_value )
{
std::cout << "In specialized version (T1 = int, T2 = char)..." <<
std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;
}

//
******************************************************************************

//TestPOD< int, long > g_test_instance ; // Works
//TestPOD< long, char > g_test_instance ; // Works


TestPOD< int, char > g_test_instance ;
// 1) E2295 Too many candidate template specializations from
'TestPOD<T1,T2>'
// 2) Define specialization - TestPOD< int, char > - uncomment lines
65-87
// Borland C++ Builder 2006 now complains...
// line 80 - E2473 Invalid explicit specialization of
'TestPOD<int,char>::eek:perator=(const int&)'
int
main( int argc, char* argv[] )
{
g_test_instance = 3 ;
return 0 ;
}
 
H

hurcan solter

I have a situation where I need to specialize a class template that
has two template parameters. Unfortunately, it needs to be
specialized for multiple cases, and, in one case, it leads to a
"conflict" - i.e., the specialization to be used is ambiguous. No
problem - since the one case specializes for the first parameter and
the other case specializes the second, I figured I could just provide
a third specialization for both parameters that covers that particular
case. Unfortunately, I'm getting errors to the effect that this
explicit specialization is not allowed. (I used the Borland C++
Builder 2006 compiler, but then I checked it using the online Comeau C+
+ compiler, which also yielded a similar error.) Can anyone explain
what I'm doing wrong? Any help would be greatly appreciated.
The code is pasted at the bottom of this message, after the diagnostic
message from the Comeau compiler.
Thanks,
Michael

Comeau C/C++ 4.3.9 (Mar 27 2007 17:24:47) for ONLINE_EVALUATION_BETA1
Copyright 1988-2007 Comeau Computing. All rights reserved.
MODE:strict errors C++ noC++0x_extensions

"ComeauTest.c", line 79: error: "const TestPOD<int, char>
&TestPOD<int,
char>::eek:perator=(const int &)" is not an entity that can be
explicitly specialized
TestPOD< int, char >::eek:perator= ( const int& source_value )
^

1 error detected in the compilation of "ComeauTest.c".

In strict mode, with -tused, Compile failed

//********* CODE STARTS HERE *************

#include <iostream>

template < typename T1, typename T2 >
struct TestPOD
{
const TestPOD< T1, T2 >&
operator= ( const T1& source_value ) ;

T1 value_ ;

} ;

template < typename T1, typename T2 >
const TestPOD< T1, T2 >&
TestPOD< T1, T2 >::eek:perator= ( const T1& source_value )
{
std::cout << "In non-specialized version..." << std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;}

//
******************************************************************************
// Specialized : T1 = int

template < typename T2 >
struct TestPOD< int, T2 >
{
const TestPOD< int, T2 >&
operator= ( const int& source_value ) ;

int value_ ;

} ;

template < typename T2 >
const TestPOD< int, T2 >&
TestPOD< int, T2 >::eek:perator= ( const int& source_value )
{
std::cout << "In specialized version (T1 = int)..." << std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;

}

//
******************************************************************************
// Specialized : T2 = char

template < typename T1 >
struct TestPOD< T1, char >
{
const TestPOD< T1, char >&
operator= ( const T1& source_value ) ;

T1 value_ ;

} ;

template < typename T1 >
const TestPOD< T1, char >&
TestPOD< T1, char >::eek:perator= ( const T1& source_value )
{
std::cout << "In specialized version (T2 = char)..." << std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;

}

//
******************************************************************************
// Specialized : T1 = int, T2 = char

template < >
struct TestPOD< int, char >
{
const TestPOD< int, char >&
operator= ( const int& source_value ) ;

int value_ ;

} ;

template < >
const TestPOD< int, char >&
TestPOD< int, char >::eek:perator= ( const int& source_value )
{
std::cout << "In specialized version (T1 = int, T2 = char)..." <<
std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;

}

//
******************************************************************************

//TestPOD< int, long > g_test_instance ; // Works
//TestPOD< long, char > g_test_instance ; // Works

TestPOD< int, char > g_test_instance ;
// 1) E2295 Too many candidate template specializations from
'TestPOD<T1,T2>'
// 2) Define specialization - TestPOD< int, char > - uncomment lines
65-87
// Borland C++ Builder 2006 now complains...
// line 80 - E2473 Invalid explicit specialization of
'TestPOD<int,char>::eek:perator=(const int&)'
int
main( int argc, char* argv[] )
{
g_test_instance = 3 ;
return 0 ;

}

since you fully specialized the class template, the member function
must be defined as a ordinary member function
(if you specialize a member function you cant specialize the class)
so removing template<> from the definition shuld do the trick.

// template<> we dont specialize this function
const TestPOD< int, char >&
TestPOD< int, char >::eek:perator= ( const int& source_value )
{
std::cout << "In specialized version (T1 = int, T2 = char)..." <<
std::endl ;
value_ = source_value ;
std::cout << "value = " << value_ << std::endl ;
return *this ;

}
 
M

michael.young

Thanks for the reply!
OK - removing the "template< >" does the trick.
I'll have to go back to the textbooks (probably "C++ Primer") for a
lesson in syntax, though.
I always thought that the "template< ... >" in the external definition
was not to specialize the function, but to indicate that it's a member
of a class template. (I believe I've seen "template< ... >
template< ... > class_name< ... >::fxn_name(...)" to define a member
function template of a class template. I could be wrong, though.) Of
course, in my example, the template parameters are fully specified, so
there is no class template - rather, it's a templated class (which, I
suppose, is still indicated by the "class_name< ... >, without the
preceding "template< ... >").
Thanks again,
Michael
 
H

hurcan solter

Thanks for the reply!
OK - removing the "template< >" does the trick.
I'll have to go back to the textbooks (probably "C++ Primer") for a
lesson in syntax, though.

I strongly suggest C++ Templates: The Complete Guide by VandeVoorde
and Josuttis. It's rather terse and overwhelming at first but it has
everything you should know and wouldn't want to know about C++
templates.
I always thought that the "template< ... >" in the external definition
was not to specialize the function, but to indicate that it's a member
of a class template. (I believe I've seen "template< ... >
template< ... > class_name< ... >::fxn_name(...)" to define a member
function template of a class template. I could be wrong, though.)

You are correct for what you've said in parentheses, you'll need one
template said:
Of course, in my example, the template parameters are fully specified, so
there is no class template - rather, it's a templated class (which, I
suppose, is still indicated by the "class_name< ... >, without the
preceding "template< ... >").

yes it's not a class template and ,no you have to indicate
template<> prefix. Vandevoorde says, it was added to disambiguate the
complex specialization cases after the member templates added the
language, which at my current level cannot come up with an example.
Thanks again,
Michael

You're welcome
Hurcan
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,995
Messages
2,570,236
Members
46,825
Latest member
VernonQuy6

Latest Threads

Top