Re: Nested templates and friends

From: Roger Leigh (${roger}_at_whinlatter.uklinux.net.invalid)
Date: 04/21/04


Date: Wed, 21 Apr 2004 09:03:16 -0000

On 2004-04-15, Alberto Barbati <AlbertoBarbati@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! =-----