Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > Nested templates and friends

Reply
Thread Tools

Nested templates and friends

 
 
Roger Leigh
Guest
Posts: n/a
 
      04-15-2004
I've written a fixed-precision class, "numeric". This stores the
number of decimal places as a template parameter. I've overloaded all
of the normal numerical operators (an example):

[Dp is the number of decimal places in the left-hand operand, and Dpr
the number in the right-hand operand.]

template<unsigned short Dp>
class numeric {
public:
// Round mode and precision are not assigned.
template<unsigned short Dpr>
numeric& operator = (const numeric<Dpr>& rhs);

template<unsigned short Dpr>
numeric& operator += (const numeric<Dpr>& rhs);

template<unsigned short Dpr>
friend numeric operator + <>(const numeric& lhs,
const numeric<Dpr>& rhs);
};

The implementation is like this:

template<unsigned short Dp>
template<unsigned short Dpr>
numeric<Dp>&
numeric<Dp>:perator = (const numeric<Dpr>& rhs)
{ ... }

template<unsigned short Dp>
template<unsigned short Dpr>
numeric<Dp>&
numeric<Dp>:perator += (const numeric<Dpr>& rhs)
{ ... }

template<unsigned short Dp>
template<unsigned short Dpr>
numeric<Dp> operator + (const numeric<Dp>& lhs,
const numeric<Dpr>& rhs)
{ ... }


While the unary operators are fine, I can't get the binary operator, a
friend, to work. I'm sure this is an issue with the template syntax,
but I can't work out what's wrong. I can't add the first template
list to the declaration, since it's within the class declaration, and
removing the <> makes no difference.


Thanks,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
 
Reply With Quote
 
 
 
 
Roger Leigh
Guest
Posts: n/a
 
      04-15-2004
Roger Leigh <${roger}@invalid.whinlatter.uklinux.net.invalid > writes:

Changing this

> template<unsigned short Dpr>
> friend numeric operator + <>(const numeric& lhs,
> const numeric<Dpr>& rhs);
> };


to this

template<unsigned short Dpr>
friend numeric operator + (const numeric& lhs,
const numeric<Dpr>& rhs);

and this

> template<unsigned short Dp>
> template<unsigned short Dpr>
> numeric<Dp> operator + (const numeric<Dp>& lhs,
> const numeric<Dpr>& rhs)
> { ... }


to this

template<unsigned short Dp, unsigned short Dpr>
numeric<Dp> operator + (const numeric<Dp>& lhs,
const numeric<Dpr>& rhs)
{ ... }

has solved this problem, though I'm not clear *why* this is the case.
My (hopefully last) remaining problem is a templated copy constructor
and assignment operator:

template<unsigned short Dp>
class numeric {
public:
template<unsigned short Dpr>
numeric (const numeric<Dpr>& rhs);
};

template<unsigned short Dp>
template<unsigned short Dpr>
EPIC::numeric<Dp>::numeric(const EPIC::numeric<Dpr>& rhs):
{ ... }

If I use "template<unsigned short Dp, unsigned short Dpr>" it's still
unhappy:

.../util/numeric.tcc:70: error: prototype for `numeric<Dp>::numeric(const
numeric<Dp>&)' does not match any in class `numeric<Dp>'

How should I declare/define this?


Thanks,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
 
Reply With Quote
 
 
 
 
Rob Williscroft
Guest
Posts: n/a
 
      04-15-2004
Roger Leigh wrote in news:(E-Mail Removed) in
comp.lang.c++:

>> template<unsigned short Dp>
>> template<unsigned short Dpr>
>> numeric<Dp> operator + (const numeric<Dp>& lhs,
>> const numeric<Dpr>& rhs)
>> { ... }

>
> to this
>
> template<unsigned short Dp, unsigned short Dpr>
> numeric<Dp> operator + (const numeric<Dp>& lhs,
> const numeric<Dpr>& rhs)
> { ... }
>
> has solved this problem, though I'm not clear *why* this is the case.


template <...> template <...> is for member templates of template
classes, your operator + is a non-member function.

> My (hopefully last) remaining problem is a templated copy constructor
> and assignment operator:
>
> template<unsigned short Dp>
> class numeric {
> public:
> template<unsigned short Dpr>
> numeric (const numeric<Dpr>& rhs);
> };
>
> template<unsigned short Dp>
> template<unsigned short Dpr>
> EPIC::numeric<Dp>::numeric(const EPIC::numeric<Dpr>& rhs):
> { ... }
>


Can you compile this:

#include <iostream>
#include <ostream>

template < unsigned D >
struct num
{
template < unsigned Dr > num( num< Dr > const &rhs );
num() {};
};

template < unsigned D >
template < unsigned Dr >
num< D >::num( num< Dr > const & )
{
std::cout << "template ctor" << std::endl;
}


int main()
{
num< 10 > n10;
num< 12 > n12( n10 );
}



> If I use "template<unsigned short Dp, unsigned short Dpr>" it's still
> unhappy:


As it should be.

>
> ../util/numeric.tcc:70: error: prototype for `numeric<Dp>::numeric>
> (const numeric<Dp>&)' does not match any in class `numeric<Dp>'
>


It maybe a bug in your compiler but surely it should be:
(const numeric< Dpr >&) in the above error message.

> How should I declare/define this?
>


namespace EPIC /* 'EPIC' BTW looks like a macro */
{
template<unsigned short Dp>
template<unsigned short Dpr>
numeric<Dp>::numeric(const numeric<Dpr>& rhs):
{
// ...
}
} /* EPIC:: */

Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
Alberto Barbati
Guest
Posts: n/a
 
      04-15-2004
Roger Leigh wrote:
>
> template<unsigned short Dp, unsigned short Dpr>
> numeric<Dp> operator + (const numeric<Dp>& lhs,
> const numeric<Dpr>& rhs)
> { ... }
>


Do you realize that your operator+ is not commutative? Expressions like
(a + b) and (b + a) could have a different types and therefore
different values, so this design looks quite error-prone to me.

It would be better to return a numeric<Dpm> where Dpm is the max between
Dp and Dpr. It's a bit tricky as a few compilers (as VC7.1, for example)
chokes about the ?: operator used in a template argument. You may try this:

template <unsigned short N, unsigned short M>
struct static_max
{
static const unsigned short value = (N > M ? N : M);
};

template <unsigned short Dp, unsigned short Dpr>
numeric< static_max<Dp, Dpr>::value >
operator+(const numeric<Dp>& lhs, const numeric<Dpr> rhs)
{...}

>
> ../util/numeric.tcc:70: error: prototype for `numeric<Dp>::numeric(const
> numeric<Dp>&)' does not match any in class `numeric<Dp>'
>


This error message is suspicious because it should have mentioned
numeric<Dp>::numeric(const numeric<Dpr>&) instead. Did you declare a
copy constructor? Unless you are happy with the implictly generated one,
you should declare it, as a template constructor is never used as a copy
constructor.

Alberto
 
Reply With Quote
 
Roger Leigh
Guest
Posts: n/a
 
      04-21-2004
On 2004-04-15, Alberto Barbati <(E-Mail Removed)> wrote:
> Roger Leigh wrote:
>>
>> template<unsigned short Dp, unsigned short Dpr>
>> numeric<Dp> operator + (const numeric<Dp>& lhs,
>> const numeric<Dpr>& rhs)
>> { ... }
>>

>
> Do you realize that your operator+ is not commutative? Expressions like
> (a + b) and (b + a) could have a different types and therefore
> different values, so this design looks quite error-prone to me.


You're right. After thinking about this, I decided on the following
design:

class numeric_base
{
protected:
numeric_base(unsigned short dp): m_dp(dp) {}
private:
unsigned short m_dp;
}

template<unsigned short Dp>
class numeric
{
public:
numeric(): numeric_base(Dp) {}
}

This has the nice property of only needing to define all the operators
in the numeric_base class, which the template then uses. The template
does nothing but give a default m_dp value.

> It would be better to return a numeric<Dpm> where Dpm is the max between
> Dp and Dpr. It's a bit tricky as a few compilers (as VC7.1, for example)
> chokes about the ?: operator used in a template argument. You may try this:
>
> template <unsigned short N, unsigned short M>
> struct static_max
> {
> static const unsigned short value = (N > M ? N : M);
> };
>
> template <unsigned short Dp, unsigned short Dpr>
> numeric< static_max<Dp, Dpr>::value >
> operator+(const numeric<Dp>& lhs, const numeric<Dpr> rhs)
> {...}


That looks quite clever, but I like to keep template magic to the
minimum, so that both I and those I work with can understand it!

>> ../util/numeric.tcc:70: error: prototype for `numeric<Dp>::numeric(const
>> numeric<Dp>&)' does not match any in class `numeric<Dp>'

>
> This error message is suspicious because it should have mentioned
> numeric<Dp>::numeric(const numeric<Dpr>&) instead. Did you declare a
> copy constructor? Unless you are happy with the implictly generated one,
> you should declare it, as a template constructor is never used as a copy
> constructor.


Ah, I didn't realise that. So I need both a template constructor and a
copy constructor.


Thanks,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
 
Reply With Quote
 
Roger Leigh
Guest
Posts: n/a
 
      04-21-2004
On 2004-04-15, Rob Williscroft <(E-Mail Removed)> wrote:
>> My (hopefully last) remaining problem is a templated copy constructor
>> and assignment operator:
>>
>> template<unsigned short Dp>
>> class numeric {
>> public:
>> template<unsigned short Dpr>
>> numeric (const numeric<Dpr>& rhs);
>> };
>>
>> template<unsigned short Dp>
>> template<unsigned short Dpr>
>> EPIC::numeric<Dp>::numeric(const EPIC::numeric<Dpr>& rhs):
>> { ... }
>>

>
> Can you compile this:
>
> #include <iostream>
> #include <ostream>
>
> template < unsigned D >
> struct num
> {
> template < unsigned Dr > num( num< Dr > const &rhs );
> num() {};
> };
>
> template < unsigned D >
> template < unsigned Dr >
> num< D >::num( num< Dr > const & )
> {
> std::cout << "template ctor" << std::endl;
> }


This works just fine (with GCC 3.3.3). However, I've changed the design
to remove the need for the template complexity.

Could anyone recommend any book or online documentation about the rules
for template syntax? I find it quite confusing. The books I have only
go into the basic usage of existing templates, and leave all this stuff
untouched.


One last template question:

If a library defines a templated function:

template<typename T>
do_foo(const T& object)
{ }

and the user is required to specalise it for their type:

class mytype;

template<>
do_foo(const mytype& object)
{ }

how should one specialise for a templated type?

template<typename T>
class mytype;

template<????>
do_foo(const mytype<??>& object)
{ }

I've tried quite a few things, like
template<> template<typename T>
but the compiler wasn't happy with any of them. Is this possible to do,
or does it require specialisation for every mytype<T> I use?


Thanks,
Roger

--
Roger Leigh

Printing on GNU/Linux? http://gimp-print.sourceforge.net/
GPG Public Key: 0x25BFB848. Please sign and encrypt your mail.


-----= Posted via Newsfeeds.Com, Uncensored Usenet News =-----
http://www.newsfeeds.com - The #1 Newsgroup Service in the World!
-----== Over 100,000 Newsgroups - 19 Different Servers! =-----
 
Reply With Quote
 
Rob Williscroft
Guest
Posts: n/a
 
      04-21-2004
Roger Leigh wrote in news:(E-Mail Removed)
in comp.lang.c++:

>
> If a library defines a templated function:
>
> template<typename T>
> do_foo(const T& object)
> { }


No return type.

>
> and the user is required to specalise it for their type:
>
> class mytype;
>
> template<>
> do_foo(const mytype& object)
> { }
>
> how should one specialise for a templated type?
>
> template<typename T>
> class mytype;
>
> template<????>
> do_foo(const mytype<??>& object)
> { }
>
> I've tried quite a few things, like
> template<> template<typename T>
> but the compiler wasn't happy with any of them. Is this possible to do,
> or does it require specialisation for every mytype<T> I use?
>


#include <iostream>
#include <ostream>

template<typename T>
void do_foo( T const & )
{
std::cout << "do_foo< T >( T const & )" << std::endl;
}


class mytype
{
};

template<>
void do_foo( mytype const & )
{
std::cout << "do_foo< mytype >( mytype const & )" << std::endl;
}



template < typename T >
class myclass_template
{
};

template < typename T >
void do_foo( myclass_template< T > const & )
{
std::cout << "do_foo< T >( myclass_template< T > const & )" << std::endl;
}

/* The above is an *overload* of do_foo< T >( T const & ), it differs
only in argument type. The previous function do_foo< mytype > is a
specialization.
*/


int main()
{
do_foo( 0 );

mytype a;
do_foo( a );

myclass_template< int > b;
do_foo( b );
}


Rob.
--
http://www.victim-prime.dsl.pipex.com/
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
MEET UR SCHOOL & COLLEGE FRIENDS. UR FRIENDS ARE WAITING FOR U.. sai.sri206@gmail.com C++ 0 10-28-2007 08:43 PM
Friends don't let friends drink and fly through space =?ISO-8859-1?Q?R=F4g=EAr?= Computer Support 6 07-29-2007 03:52 AM
how to Specializations of function Templates or Overloading Function templates with Templates ? recover C++ 2 07-25-2006 02:55 AM
member functions as friends - friends of each other? bipod.rafique@gmail.com C++ 2 07-16-2005 10:55 AM
Templates templates templates JKop C++ 3 07-21-2004 11:44 AM



Advertisments