473,320 Members | 1,950 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,320 software developers and data experts.

Nested templates and friends

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>::operator = (const numeric<Dpr>& rhs)
{ ... }

template<unsigned short Dp>
template<unsigned short Dpr>
numeric<Dp>&
numeric<Dp>::operator += (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! =-----
Jul 22 '05 #1
6 1487
Roger Leigh <${******@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! =-----
Jul 22 '05 #2
Roger Leigh wrote in news:87************@wrynose.whinlatter.uklinux.net 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/
Jul 22 '05 #3
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
Jul 22 '05 #4
On 2004-04-15, Alberto Barbati <Al************@libero.it> 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! =-----
Jul 22 '05 #5
On 2004-04-15, Rob Williscroft <rt*@freenet.co.uk> 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! =-----
Jul 22 '05 #6
Roger Leigh wrote in news:tn************@system10.lan.epictechnology.co .uk
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/
Jul 22 '05 #7

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: Alexander Stippler | last post by:
Hi what's wrong about the following code? It does not compile. template <typename T> class A { public: class B; };
1
by: Gianni Mariani | last post by:
I have 2 distinct template classes which co-operate, hence are friends. However, I can't seem to figure out what syntax to use to make this work. What is the right(tm) way to write a friend...
6
by: oooooo0000000 | last post by:
I have an XML file of varying nesting depth... <catalouge> <item id="1"> <name/> <item id="23"> <name/> <item id="55"> <name/> </item>
3
by: Andriy Shnyr | last post by:
Let us consider the following nested templates case: template<typename T> class Outer{ public: template<typename U> class Inner{ public:
11
by: Micha | last post by:
Hello there, I think I've run into some classic c++ pitfall and maybe some of you guys can help me out. For my project I will need to use matrices and vectors and so I decided to implement them...
8
by: Robert W. | last post by:
I've almost completed building a Model-View-Controller but have run into a snag. When an event is fired on a form control I want to automatically updated the "connnected" property in the Model. ...
25
by: Ted | last post by:
I'm putting the posts that follow here (hopefully they will follow here!) because they were rejected in comp.lang.c++.moderated. It behooves anyone reading them to first read the the thread of the...
3
by: CrazyAtlantaGuy | last post by:
I am working on creating an XSLT that transforms Html into an XML format that can be imported into Framemaker. The challenge, it turns out, is correctly transforming the flat html header tags...
4
by: aaragon | last post by:
Hi everyone, I was unable to find out why my code is not compiling. I have a template class and I'm trying to write the operator<< for standard output. Does anyone know why this is not right?...
0
by: ryjfgjl | last post by:
ExcelToDatabase: batch import excel into database automatically...
0
isladogs
by: isladogs | last post by:
The next Access Europe meeting will be on Wednesday 6 Mar 2024 starting at 18:00 UK time (6PM UTC) and finishing at about 19:15 (7.15PM). In this month's session, we are pleased to welcome back...
0
by: Vimpel783 | last post by:
Hello! Guys, I found this code on the Internet, but I need to modify it a little. It works well, the problem is this: Data is sent from only one cell, in this case B5, but it is necessary that data...
1
by: PapaRatzi | last post by:
Hello, I am teaching myself MS Access forms design and Visual Basic. I've created a table to capture a list of Top 30 singles and forms to capture new entries. The final step is a form (unbound)...
1
by: Defcon1945 | last post by:
I'm trying to learn Python using Pycharm but import shutil doesn't work
1
by: Shællîpôpï 09 | last post by:
If u are using a keypad phone, how do u turn on JavaScript, to access features like WhatsApp, Facebook, Instagram....
0
by: af34tf | last post by:
Hi Guys, I have a domain whose name is BytesLimited.com, and I want to sell it. Does anyone know about platforms that allow me to list my domain in auction for free. Thank you
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 3 Apr 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome former...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.