constructor specialization

A

Adam Badura

Hi!

I have a class like:

template<int size_integer, int size_fraction>
class number {

template<typename charT, typename traitsT>
explicit number(const charT* textual, int radix = 10);

template<typename charT>
explicit number<charT, std::char_traits<charT> >(const charT* textual,
int radix = 10); // line 25

}; // line 47

My compiler (MS VS .NET 2005) claims on the second declaration.

j:\number\number.hpp(25) : error C2975: 'number_library::number' : invalid
templ
ate argument for 'size_integer', compile-time evaluatable constant
expression ex
pected
j:\number\number.hpp(47) : see declaration of
'number_library::number'
j:\number\number.hpp(47) : see reference to class template
instantiation
'number_library::number<size_integer,size_fraction>' being compiled

So it is clear that the compiler understends it as a class specialization.
How to avoid it? How to specialzie constructor?

Perhabs this is totaly wrong thing I'm tring to do (I do not have much
experinece with templates). What I want to achive is to have a constructor
which
a) can construct number form textual representation (obviously)
b) do not have to write to versions (for char and wchar_t)
c) allow users to use their types and traits
d) allow simple constructions like

number<10, 10> big = "1000000000000000000000000000000";

But this does not work if I have only one constructor parametrized with
char type and traits type becauce traits type cannot be deducted by the
compiler. My compiler (or the language itself?) does not allow me to have
default parameters here in function. And I don't want to write two versions:
for default traits and parmetrized.

What and how (and why) to do?

Thanks in advance.

Adam Badura

P.S. It is not my homework. I do it for fun and exercise.
 
A

Adam Badura

And the next question is how to make MAX or MIN in template
specialization.

template<int size_integer1T, int size_fraction1T, int size_integer2T, int
size_fraction2T>
number< (size_integer1T > size_integer2T ? size_integer1T :
size_integer2T),
(size_fraction1T > size_fraction2T ? size_fraction1T :
size_fraction2T) >
operator +(const number<size_integer1T, size_fraction1T>& v1, const
number<size_integer1T, size_fraction1T>& v2);

I want the global operator + to return typ capable of stroing the hole
result. So I need to MAX of the fraction and integer parts. operator ?: does
not work... What to do?

Adam Badura
 
A

Adam Badura

template<int size_integer1T, int size_fraction1T, int size_integer2T, int
size_fraction2T>
number< (size_integer1T > size_integer2T ? size_integer1T :
size_integer2T),
(size_fraction1T > size_fraction2T ? size_fraction1T :
size_fraction2T) >
operator +(const number<size_integer1T, size_fraction1T>& v1, const
number<size_integer1T, size_fraction1T>& v2);

Naturally the second parameter of the operaotr should be
number<size_integer2T, size_fraction2T>
instead of
number<size_integer1T, size_fraction1T>

Sorry for that mistake. But now not only I have a bad code, but the
compiler (MS VS .NET 2005) ends with an intenral error... :)

Adam Badura
 
V

Victor Bazarov

Adam said:
I have a class like:

template<int size_integer, int size_fraction>
class number {

template<typename charT, typename traitsT>
explicit number(const charT* textual, int radix = 10);

template<typename charT>
explicit number<charT, std::char_traits<charT> >(const charT*
textual, int radix = 10); // line 25

}; // line 47

My compiler (MS VS .NET 2005) claims on the second declaration.

j:\number\number.hpp(25) : error C2975: 'number_library::number' :
invalid templ
ate argument for 'size_integer', compile-time evaluatable constant
expression ex
pected
j:\number\number.hpp(47) : see declaration of
'number_library::number'
j:\number\number.hpp(47) : see reference to class template
instantiation
'number_library::number<size_integer,size_fraction>' being compiled

So it is clear that the compiler understends it as a class
specialization. How to avoid it? How to specialzie constructor?

(a) There are no partial specialisations of functions

(b) You cannot specialise a member inside the class definition (IIRC)

(c) You don't need to specialise your constructor template, simply
overload it.
Perhabs this is totaly wrong thing I'm tring to do (I do not have
much experinece with templates). What I want to achive is to have a
constructor which
a) can construct number form textual representation (obviously)
b) do not have to write to versions (for char and wchar_t)
c) allow users to use their types and traits
d) allow simple constructions like

number<10, 10> big = "1000000000000000000000000000000";

....and that's why you declared your c-tors "explicit"?... Never mind.
With explicit c-tors you only can do

number said:
But this does not work if I have only one constructor parametrized
with char type and traits type becauce traits type cannot be deducted
by the compiler. My compiler (or the language itself?) does not allow
me to have default parameters here in function.
Huh?

And I don't want to
write two versions: for default traits and parmetrized.

What and how (and why) to do?

template<int size_integer, int size_fraction>
class number {

// how do you suppose to use 'traitsT' here:
template<typename charT, typename traitsT>
explicit number(const charT* textual, int radix = 10);
// ??

template<typename charT>
explicit number(const charT* textual, int radix = 10);
};

The user of your type will not be able to supply traitsT. In order to
be able to recognize those you need to give your constructor an argument
that would help the compiler to deduce 'traitsT'.

Another way is to make your 'traitsT' an argument of the class template
and _there_ you will be able to supply default argument:


template<int size_integer, int size_fraction,
template<class> traitsT = std::char_traits >
class number {
template<typename charT>
explicit number(const charT* textual, int radix = 10);
// use 'traitsT' somehow...
};

Now, the user will be able to say

number<10,10,mytraits> big("blahblahblahblah",36);

V
 
V

Victor Bazarov

Adam said:
And the next question is how to make MAX or MIN in template
specialization.

template<int size_integer1T, int size_fraction1T, int size_integer2T,
int size_fraction2T>
number< (size_integer1T > size_integer2T ? size_integer1T :
size_integer2T),
(size_fraction1T > size_fraction2T ? size_fraction1T
: size_fraction2T) >
operator +(const number<size_integer1T, size_fraction1T>& v1, const
number<size_integer1T, size_fraction1T>& v2);

I want the global operator + to return typ capable of stroing the
hole result. So I need to MAX of the fraction and integer parts.
operator ?: does not work... What to do?

You need a template MAX and MIN:

template<int a, int b> struct MAX { enum { value = (a > b ? a : b) }; };
template<int a, int b> struct MIN { enum { value = (a < b ? a : b) }; };

template<int i> struct T { int foo() { return i;} };
template<int j, int k> T<MAX<j,k>::value> operator +(T<j>, T<k>) {
return T<MAX<j,k>::value>();
}
int main() {
T<10> t10;
T<20> t20;
return (t10+t20).foo();
}

V
 
A

Adam Badura

You need a template MAX and MIN:
template<int a, int b> struct MAX { enum { value = (a > b ? a :
b) }; };
template<int a, int b> struct MIN { enum { value = (a < b ? a :
b) }; };

Thx.

Adam Badura
 
A

Adam Badura

(c) You don't need to specialise your constructor template, simply
overload it.

Oh... Right. Good point. My mistake not to think about it.
...and that's why you declared your c-tors "explicit"?... Never mind.
With explicit c-tors you only can do

number<10,10> big("1000000000000000000000000000000");

Are not this constructs equal? I thought both use constructor....
template<int size_integer, int size_fraction>
class number {

// how do you suppose to use 'traitsT' here:
template<typename charT, typename traitsT>
explicit number(const charT* textual, int radix = 10);
// ??

template<typename charT>
explicit number(const charT* textual, int radix = 10);
};

Good point. I thought about removing them as useless. But then I was not
sure if i would not require them while parsing for white spaces for example.
And I just made it to chcecif I can and how to do it (as I wrote it is not
homework, project or something like this - I do it for fun and excercise)
The user of your type will not be able to supply traitsT. In order to
be able to recognize those you need to give your constructor an argument
that would help the compiler to deduce 'traitsT'.

Will not be able? Will not he/she be able to explicitly specialize
constructor with types he wants?
Another way is to make your 'traitsT' an argument of the class template
and _there_ you will be able to supply default argument:

This is possibel but seems "strange". This is just a constructor to ease
life, and char traits do not have much in common wiht number type.

Adam Badura
 

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,981
Messages
2,570,188
Members
46,731
Latest member
MarcyGipso

Latest Threads

Top