Re: Explicit specialization of a template.
On Feb 8, 8:08 pm, Ian Collins <ian-n...@hotmail.com> wrote:
ZikO wrote:
there's the simple template of the function which converts a
number into bits as below:
template<class T>
const std::string toBits(const T& n, const char& sep = '\0')
<snip>
Now. I don't want the function to operate on double / float
/ long double / bool etc. I've supplied the code with
explicit specializations:
template<>
const std::string toBits<double>(const double& n, const char& sep = '=
\0') {
return string("It is not allowed to use bit operands on double type=
");
4 times for all four floating types. I cannot compile the code. The
compiler says for every specialization the same error:
error: default argument specified in explicit specialization
That's write, you can't. Just write
That's right, you can't:-).
template<>
const std::string toBits(const double& n, const char& ) {
return std::string("It is not allowed to use bit operands on double
type");}
Why the the second parameter a const reference?
The second thing is I don't know how I could simply
eliminate any other types which is not char int or its
derivative like short long etc. let's say if someone try to
pass object of X class I would like compiler to use general
specialization of the function which stays it's wrong type.
Not using specialisation. You could include an assignment to
the largest supported integral type in the function which
would fail to compile for types that can't be converted.
Except that that might prevent instantiation on user defined
types which behave like integers.
I'm not sure I see the problem. Without the specialization, he
should get a compile time error if he instantiates the function
over a double, because he uses the shift operator in the
function. His function can only be instantiated over types for
which the shift operator is legal. If he wants a better error
message, he should be able to use something along the lines of:
int instantiation_type_must_be_integer[
std::numeric_limits< T >::is_integer ] ;
If he really does want to defer the error until runtime, of
course, he can have the function call an overloaded function:
template< bool b > struct Discrim {} ;
template< typename T >
std::string
toBits(
T n,
Discrim< false > )
{
return "some error message" ;
}
template< typename T >
std::string
toBits(
T n,
Discrim< true > )
{
char result[ sizeof( n ) * CHAR_BIT ] ;
char* dest = result + sizeof( result ) ;
while ( dest != result ) {
*dest = "01"[ n & 1 ] ;
n >>= 1 ;
-- dest ;
}
return std::string( result, result + sizeof( result ) ) ;
}
template< typename T >
std::string
toBits(
T n )
{
return toBits(
n,
Discrim< numeric_limits< T >::is_integer >() ) ;
}
Or he could drop the error entirely, and support dumping the
underlying bit pattern of anything, by reinterpret_cast'ing the
address of the object to unsigned char*:
template< typename T >
std::string
toBits(
T const& n )
{
char result[ sizeof( n ) * CHAR_BIT ] ;
char* dest = result + sizeof( result ) ;
unsigned char const*p
= reinterpret_cast< unsigned char const* >( &n + 1 ) ;
while ( p != reinterpret_cast< unsigned char const* >( &n ) )
{
-- p ;
unsigned char byte = *p ;
for ( std::size_t count = CHAR_BIT ; count != 0 ; --
count ) {
*dest = "01"[ byte & 1 ] ;
byte >>= 1 ;
-- dest ;
}
}
return std::string( result, result + sizeof( result ) ) ;
}
--
James Kanze (GABI Software) email:james.kanze@gmail.com
Conseils en informatique orient=E9e objet/
Beratung in objektorientierter Datenverarbeitung
9 place S=E9mard, 78210 St.-Cyr-l'=C9cole, France, +33 (0)1 30 23 00 34