templated type and numeric_limits?

D

Dave Johansen

Is it possible to specialized numeric_limits with a templated type?

For example:


template<unsigned int DIGITS>
class BigInt
{
...
};

template<unsigned int DIGITS>
template<> class std::numeric_limits<BigInt<DIGITS> >
{
...
};

I tried this with Visual C++ 2008 and it spit out the error "error
C2913: explicit specialization; 'std::numeric_limits<BigInt<DIGITS>>'
is not a specialization of a class template".

Is there a way to make this work? Or is explicit specialization using
a templated typed not allowed in C++?

Thanks,
Dave
 
S

SG

Is it possible to specialized numeric_limits with a templated type?

Sure.

template<unsigned int DIGITS>
class BigInt;

template<unsigned int DIGITS>
class std::numeric_limits<BigInt<DIGITS> >
{
// ...
};
Is there a way to make this work? Or is explicit specialization using
a templated typed not allowed in C++?

It is for class/struct templates.


Cheers!
SG
 
S

SG

  template<unsigned int DIGITS>
  class std::numeric_limits<BigInt<DIGITS> >
  {
    // ...
  };

Sorry. This is a copy&paste bug. I didn't see your full qualification
std::numeric_limits. This is not going to work. You need to remove
"std::" here and put this partial specialization inside "namespace std
{}".

Cheers!
SG
 
D

David Johansen

Thanks for the tip because it worked, but I guess I'm missing
something and I don't get how/why this works. Is the syntax for a
explicit specialization of a class when using a templated typed
different? Or is something else going on that I'm not realizing?

Because if I do something like this:

class test
{
};

class std::numeric_limits<test>
{
};

Then it doesn't compile without the "template<>", so what am I not
getting?

Thanks again,
Dave
 
N

Noah Roberts

Dave said:
Is it possible to specialized numeric_limits with a templated type?

For example:


template<unsigned int DIGITS>
class BigInt
{
...
};

template<unsigned int DIGITS>
template<> class std::numeric_limits<BigInt<DIGITS> >
{
...
};

Try the correct syntax.

namespace std
{
template < unsigned int DIGITS >
class numeric_limits<BigInt<DIGITS> >
{
};
}
 
B

Bart van Ingen Schenau

Thanks for the tip because it worked, but I guess I'm missing
something and I don't get how/why this works. Is the syntax for a
explicit specialization of a class when using a templated typed
different? Or is something else going on that I'm not realizing?

Because if I do something like this:

class test
{

};

class std::numeric_limits<test>
{

};

Then it doesn't compile without the "template<>", so what am I not
getting?

When you specialize a class template, you put the remaining template
parameters of the (partial) specialization after the template keyword.
So, when you specialize on a template or otherwise don't fully specify
the type, the specialization starts with 'template </*something*/>'.
When you specialize on a single concrete type, there are no remaining
template parameters, so the specialization starts with 'template <>'.

In an example:

// Base template
template <class T>
class traits {};

// (Partial) specialization for pointers
template <class T>
class traits< T* > {};

// (Partial) specialization for Complex<T>
template <class T>
class traits< Complex<T> > {};

// (Partial) specialization for Bignum<DIGITS>
template <unsigned DIGITS>
class traits< Bignum<DIGITS> > {};

// (Full) specialization for int
template <>
class traits< int > {};

Note that the compiler can differentiate between a base template and a
specialization based on these observations:
- For a specialization, the name of the template must have been seen
before by the compiler.
- The first token after the name in a specialization is a '<'.
Thanks again,
Dave

Bart v Ingen Schenau
 
J

James Kanze

Thanks for the tip because it worked, but I guess I'm missing
something and I don't get how/why this works. Is the syntax
for a explicit specialization of a class when using a
templated typed different? Or is something else going on that
I'm not realizing?
Because if I do something like this:
class test
{
};
class std::numeric_limits<test>
{
};
Then it doesn't compile without the "template<>", so what am I
not getting?

In order to explicitly specialize a template with a single type
parameter (like std::numeric_limits), you need a type. A class
is a type; a class template is *not*. What SG provided is not
an explicit specialization, but a partial specialization,
something different, which obeys different rules. You could
also use an explicit specialization (using template<>), but only
for a specific type, e.g.:

template<>
class std::numeric_limits< BigInt< 200 > >
{
// ...
} ;

SG's suggestion, using partial specialization, is probably what
you want, however.
 
D

David Johansen

I guess that I just wasn't familiar with partial specialization and
its uses, but it good to know now and it's now 1 more tool in my belt.
Dave
 
D

David Johansen

Thanks for the clarification. I agree that explicit specialization
would be a pain and impractical, so I'll go with the partial
specialization.
Thanks,
Dave
 
L

Lionel B

Try the correct syntax.

namespace std
{
template < unsigned int DIGITS >
class numeric_limits<BigInt<DIGITS> > {
};
}

Out of interest, is it not generally frowned upon to add functionality to
namespace std (presumably on the grounds that it is then no longer
"standard" and creates potential confusion)? Not that I can see much
potential for confusion in this particular case (which I have in fact used
myself).
 
J

James Kanze

Out of interest, is it not generally frowned upon to add
functionality to namespace std (presumably on the grounds that
it is then no longer "standard" and creates potential
confusion)? Not that I can see much potential for confusion in
this particular case (which I have in fact used myself).

It's undefined behavior to define anything in std::, *except* to
specialize an existing template for a user defined type.
 
B

Bo Persson

Lionel said:

One reason for this, of course, is that we cannot know what
specializations, performance enhancing or otherwise, the implementor
of the library has already provided. Except that he cannot already
have specializations for our user defined types.


Bo Persson
 
B

Bo Persson

Bo said:
One reason for this, of course, is that we cannot know what
specializations, performance enhancing or otherwise, the implementor
of the library has already provided. Except that he cannot already
have specializations for our user defined types.

And, besides, the hard rule is: Because the standard says so!

:)


Bo Persson
 
A

Alan Woodland

James said:
In order to explicitly specialize a template with a single type
parameter (like std::numeric_limits), you need a type. A class
is a type; a class template is *not*. What SG provided is not
an explicit specialization, but a partial specialization,
something different, which obeys different rules. You could
also use an explicit specialization (using template<>), but only
for a specific type, e.g.:

template<>
class std::numeric_limits< BigInt< 200 > >
{
// ...
} ;

SG's suggestion, using partial specialization, is probably what
you want, however.

I'd always assumed that specialising something counted as a declaration,
and hence because the namespace in question is std would be considered
UB. Is that not the case and specialising is permitted or is this an
exception to that?

Alan
 
J

James Kanze

Is it possible to specialized numeric_limits with a templated
type?

Maybe. What do you mean by "a templated type"? A type that is
a specialization of a template? If so, no problem. A class
template? If so, it's not a type (so your nomenclature is
wrong), and can only be used to specialize a template which
takes a template parameter.
For example:
template<unsigned int DIGITS>
class BigInt
{
...
};

OK. That's a class template. Not yet a type (but individual
specializations will be types).
template<unsigned int DIGITS>
template<> class std::numeric_limits<BigInt<DIGITS> >
{
...
};

std::numeric_limits requires a type. If DIGITS is defined, then

template<>
class std::numeric_limits< BigInt< DIGITS > > { /* ... */ } ;

is fine. What you're probably looking for, however, is partial
specialization, which is somewhat different from actual
specialization (it doesn't create a type, for example), and has
a different syntax:

template< unsigned int DigitCount >
class std::numeric_limits< BigInt< DigitCount > >
{
// ...
} ;

This tells the compiler to use this definition if it has a
specialization of numeric_limits whose type matches BigInt<
DigitCount >.
I tried this with Visual C++ 2008 and it spit out the error
"error C2913: explicit specialization;
'std::numeric_limits<BigInt<DIGITS>>' is not a specialization
of a class template".

Probably because DIGITS wasn't a constant expression.
Is there a way to make this work? Or is explicit
specialization using a templated typed not allowed in C++?

If there were a class template:

template< template< unsigned int D > C > class Xyz ...

you could instantiate it with your class template BigInt, e.g.:

Xyz< BigInt > instance ;

But that's not the case for std::numeric_limits; what you're
looking for is partial specialization.
 

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

Forum statistics

Threads
473,982
Messages
2,570,189
Members
46,735
Latest member
HikmatRamazanov

Latest Threads

Top