Saturday, July 25, 2009

comp.lang.c++ - 8 new messages in 3 topics - digest

comp.lang.c++
http://groups.google.com/group/comp.lang.c++?hl=en

comp.lang.c++@googlegroups.com

Today's topics:

* Implicit conversion for operator - 5 messages, 3 authors
http://groups.google.com/group/comp.lang.c++/t/09f60c8535938843?hl=en
* How can I use unqualified names? (Possibly hard or impossible?) - 1 messages,
1 author
http://groups.google.com/group/comp.lang.c++/t/e2f24a95fe72b591?hl=en
* why unsigned char not work - 2 messages, 2 authors
http://groups.google.com/group/comp.lang.c++/t/e23f6c160b89ad0a?hl=en

==============================================================================
TOPIC: Implicit conversion for operator
http://groups.google.com/group/comp.lang.c++/t/09f60c8535938843?hl=en
==============================================================================

== 1 of 5 ==
Date: Fri, Jul 24 2009 8:14 pm
From: Victor Bazarov


pikalaw wrote:
> Need help figuring out why the following code fails to compile:
>
> #include <complex>
> #include <boost/rational.hpp>
>
> int main()
> {
> using namespace std;
> using namespace boost;
>
> complex<rational<int> > z;
> const complex<rational<int> > j(0,1);
>
> z = 3 + 2 * j; // (1). won't
> compile. complains about no matching operator*.
> z = 3 + rational<int>(2) * j; // (2). but this works.
> note the explicit conversion.
>
> return 0;
> }
>
> The compiler error, generated by gcc version 4.0.1 (Apple Inc. build
> 5490), was
>
> boost/operators.hpp:251: note:
> candidates are: boost::rational<int> boost::operator*(const
> boost::rational<int>&, const int&)
> boost/operators.hpp:251: note:
> boost::rational<int> boost::operator*(const int&, const
> boost::rational<int>&)
> boost/operators.hpp:251: note:
> boost::rational<int> boost::operator*(const
> boost::rational<int>&, const boost::rational<int>&)
>
> What bugs [pun] me is why didn't the compiler try the operator
>
> std::complex<boost::rational<int> >
> std::operator*(
> const boost::rational<int>&,
> const std::complex<boost::rational<int> >&)
>
> for (1) by promoting the integer constant 2 to rational<int>? But if
> I explicitly convert it as in (2), then it finds this operator.
>
> Please illuminate me!

The library only defines, literally:

template<class T> complex<T> operator*(const T&, const complex<T>&);

operator for multiplication. For the expression '2 * j' it tries to
come to a conclusion what 'T' should be. It can be 'int', or it can be
'rational<int>'. The implicit conversions are not applied when deducing
template arguments. If 'T' is 'int' (from the first argument), the
second argument does not match. If it's 'rational<int>' (from the
second argument), the first argument's type does not match. So, the
compiler discards the template operator*. No other operator* suits the
expression since 'complex<rational<int> >' is not convertible to any of
the multipliers of 'int'.

If it's unclear, ask more questions.

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask


== 2 of 5 ==
Date: Fri, Jul 24 2009 8:19 pm
From: Stephen Horne


On Fri, 24 Jul 2009 19:24:06 -0700 (PDT), pikalaw <pikalaw@gmail.com>
wrote:

>An update:
>
>Even this simplified code does not compile.

> complex<long > y;
> const complex<long > k(0,1);
>
> y = 2 * k;

>But if I replace the constant 2 with 2L, the long version, then it
>compiles.

When you use the literal 2, I suspect two conversions are needed...

2 -> 2L (from integer to long)

2L -> <complex 2> (from long to complex)

IIRC, conversions are only done implicitly if they can be achieved in
a single step.

== 3 of 5 ==
Date: Fri, Jul 24 2009 10:22 pm
From: pikalaw


On Jul 24, 11:14 pm, Victor Bazarov <v.Abaza...@comAcast.net> wrote:
> pikalaw wrote:
> > Need help figuring out why the following code fails to compile:
>
> > #include <complex>
> > #include <boost/rational.hpp>
>
> > int main()
> > {
> > using namespace std;
> > using namespace boost;
>
> >                    complex<rational<int> > z;
> >         const   complex<rational<int> > j(0,1);
>
> >         z = 3 + 2 * j;                         // (1).  won't
> > compile.  complains about no matching operator*.
> >         z = 3 + rational<int>(2) * j;     // (2).  but this works.
> > note the explicit conversion.
>
> >         return 0;
> > }
>
> > The compiler error, generated by gcc version 4.0.1 (Apple Inc. build
> > 5490), was
>
> > boost/operators.hpp:251: note:
> >         candidates are: boost::rational<int> boost::operator*(const
> > boost::rational<int>&, const int&)
> > boost/operators.hpp:251: note:
> >         boost::rational<int> boost::operator*(const int&, const
> > boost::rational<int>&)
> > boost/operators.hpp:251: note:
> >         boost::rational<int> boost::operator*(const
> > boost::rational<int>&, const boost::rational<int>&)
>
> > What bugs [pun] me is why didn't the compiler try the operator
>
> >         std::complex<boost::rational<int> >
> >         std::operator*(
> >                 const boost::rational<int>&,
> >                 const std::complex<boost::rational<int> >&)
>
> > for (1) by promoting the integer constant 2 to rational<int>?  But if
> > I explicitly convert it as in (2), then it finds this operator.
>
> > Please illuminate me!
>
> The library only defines, literally:
>
>     template<class T> complex<T> operator*(const T&, const complex<T>&);
>
> operator for multiplication.  For the expression '2 * j' it tries to
> come to a conclusion what 'T' should be.  It can be 'int', or it can be
> 'rational<int>'.  The implicit conversions are not applied when deducing
> template arguments.  If 'T' is 'int' (from the first argument), the
> second argument does not match.  If it's 'rational<int>' (from the
> second argument), the first argument's type does not match.  So, the
> compiler discards the template operator*.  No other operator* suits the
> expression since 'complex<rational<int> >' is not convertible to any of
> the multipliers of 'int'.

It seems that implicit type-conversion is only allowed with non-
template functions. Had I declared

complex<long> operator*(long a, const complex<long> &z)

then the expression '2 * k' compiles fine.

However, with template version of functions, implicit type-conversion
is not done.

BTW, is this behavior in the C++ standard? Or one of those
unspecified, implementation-dependent behavior?

>
> If it's unclear, ask more questions.
>
> V
> --
> Please remove capital 'A's when replying by e-mail
> I do not respond to top-posted replies, please don't ask

== 4 of 5 ==
Date: Fri, Jul 24 2009 10:22 pm
From: pikalaw


On Jul 24, 11:09 pm, Ian Collins <ian-n...@hotmail.com> wrote:
> pikalaw wrote:
> > An update:
>
> > Even this simplified code does not compile.
>
> > #include <complex>
>
> > using namespace std;
>
> > int main()
> > {
> >                 complex<long >  y;
> >         const   complex<long >  k(0,1);
>
> >         y = 2 * k;
>
> >         return 0;
> > }
>
> > But if I replace the constant 2 with 2L, the long version, then it
> > compiles.
>
> What else did you expect?  int != long.
>

Well, but int can implicitly convert to long, no?

> --
> Ian Collins

== 5 of 5 ==
Date: Fri, Jul 24 2009 10:27 pm
From: pikalaw


On Jul 24, 11:19 pm, Stephen Horne <sh006d3...@blueyonder.co.uk>
wrote:
> On Fri, 24 Jul 2009 19:24:06 -0700 (PDT), pikalaw <pika...@gmail.com>
> wrote:
>
> >An update:
>
> >Even this simplified code does not compile.
> >                complex<long >  y;
> >        const   complex<long >  k(0,1);
>
> >        y = 2 * k;
> >But if I replace the constant 2 with 2L, the long version, then it
> >compiles.
>
> When you use the literal 2, I suspect two conversions are needed...
>
>   2 -> 2L  (from integer to long)
>
>   2L -> <complex 2> (from long to complex)
>
> IIRC, conversions are only done implicitly if they can be achieved in
> a single step.

I checked the stl source, the template defines the operator template

complex<T> operator*(const T &, const complex<T>);

So, I had expected this template to instantiate into

complex<long> operator*(const long &, const complex<long> &)

which with one implicit conversion from int to long would allow '2 *
k' be called.

But it didn't.

==============================================================================
TOPIC: How can I use unqualified names? (Possibly hard or impossible?)
http://groups.google.com/group/comp.lang.c++/t/e2f24a95fe72b591?hl=en
==============================================================================

== 1 of 1 ==
Date: Fri, Jul 24 2009 11:28 pm
From: "Alf P. Steinbach"


* James Kanze:
> On Jul 19, 5:12 pm, "Alf P. Steinbach" <al...@start.no> wrote:
>> Original problem: a pack of options that may contain a great
>> many simple numerical and bitset options (defined by external
>> API), and that should be (1) extensible for at least two
>> levels, like class derivation, (2) easy to define, (3) easily
>> constructible specifying only those options of interest,
>> defaulting on the rest, (4) clean notation for accessing
>> options, with compile time checking, and (5) if possible as
>> efficient as possible access of options.
>
> Sounds like something in a GUI:-).

Right on. :-)

I let it simmer for a time, actually I think it's been a week now, hoping for
fresh ideas.

But in the end I now just combined your member routines suggestion with my
previous idea of options as types.


>> My silly idea: represent option names as types, and support
>> creation notation like
>
>> Options() << x(42) << alpha(3.14)
>
>> where 'x' and 'alpha' and other option names are type names.
>> This allows compile time access of options via notation like
>> 'options::x.member' or e.g. 'options.member<x>', with
>> efficiency as for ordinary member access. Defining a set of
>> options is reasonably simple, given a little template-based
>> support.
>
> Not silly at all. It's very similar to the "standard" solution,
> which would also use an Options class, but with member functions
> which chain (i.e. return an Options&):
>
> Options().x( 42 ).alpha( 3.14 ) ...
>
> I usually provide a copy constructor for Options as well, so
> that the client can set up special defaults for specific cases,
> e.g.:
>
> Options( warningPopup ).x( 42 )
>
> (where warningPopup is a static variable of type Options, with
> some different set of options than the usual default).
>
>> Problem: long qualified option names are impractical and
>> unreadable, but short good names like 'x' can easily conflict
>> with client code. Especially where that client code cretating
>> an Options instance is a constructor initializer list a 'using
>> namespace...' isn't practical (as far as I can see, but I may
>> be wrong). I started thinking in terms of ADL and such, but
>> no dice: my brain cannot come up with good solution, even now
>> after having slept on it!
>
> The member function solution works for me. The one disadvantage
> I can see is that you have to type out all of the member
> functions; I'll usually use a simple AWK script to generate the
> class, so I don't even have to do this.

Uh huh? Why not macros & templates & stuff? Pure C++ solution?


> (The script will
> convert a file containing lines something like:
> optionName optionType defaultValue
> into a complete class definition, with all of the necessary
> access functions and the member variables.)

My test usage code for all-C++ solution now looks like this:


<code>
//------------------------ Usage:

#include <iostream>

namespace blahblah {
namespace reallyLongName {
namespace california {
CPPX_DEFINE_OPTION( x, double )
CPPX_DEFINE_OPTION( y, double )
CPPX_DEFINE_2OPTIONCLASS( Pos2Options, cppx::options::NoBase, x, y )

CPPX_DEFINE_OPTION( z, double )
CPPX_DEFINE_1OPTIONCLASS( Pos3Options, Pos2Options, z )
}}} // namespace blahblah::reallyLongName::california

struct UserClass1
{
typedef ::blahblah::reallyLongName::california::Pos2Options
Pos2Options;

UserClass1( Pos2Options const& options )
{
using namespace std;
cout << options.x() << endl;
cout << options.y() << endl;
}
};

struct UserClass2: UserClass1
{
typedef ::blahblah::reallyLongName::california::Pos3Options
Pos3Options;

UserClass2( Pos3Options const& options )
: UserClass1( options )
{
using namespace std;
cout << std::endl;
cout << options.x() << endl;
cout << options.y() << endl;
cout << options.z() << endl;
}
};

int main()
{
typedef UserClass2::Pos3Options Pos3Options;
UserClass2( Pos3Options().x( 3.14 ).z( 42 ) );
}
</code>


<results>
3.14
0

3.14
0
42
</results>


Works with both g++ and MSVC.

I'm interested in whether anyone can find a /simple/ way to do it, because the
support needed to get that final

Pos3Options().x( 3.14 ).z( 42 )

expression to work turned out, with the way I did it, to be a little in-elegant
(I guess that's what some folks call "too smart" code)...


Cheers, & thanks,

- Alf

==============================================================================
TOPIC: why unsigned char not work
http://groups.google.com/group/comp.lang.c++/t/e23f6c160b89ad0a?hl=en
==============================================================================

== 1 of 2 ==
Date: Fri, Jul 24 2009 11:28 pm
From: Paavo Helde


Paul Brettschneider <paul.brettschneider@yahoo.fr> kirjutas:

> Ian Collins wrote:
>
>> Paul Brettschneider wrote:
>>> Alf P. Steinbach wrote:
>>>
>>>> * Jerry Coffin:
>>>>> In article <71a838a8-a116-4ce4-b309-43555a6bd406
>>>>> @h31g2000yqd.googlegroups.com>, james.kanze@gmail.com says...
>>>>>
>>>>> [ ... ]
>>>>>
>>>>>> It is an interesting point, however: it does mean that C++ isn't
>>>>>> implementable under 64 bit Windows.
>>>>> It doesn't mean anything of the sort. The current implementations
>>>>> may not conform, but that's completely different from it being
>>>>> impossible to create an implementation that does conform. Just for
>>>>> example, they could have 8-bit char, 16-bit short, 32-bit int,
>>>>> 64-bit long, and size_t a typedef for long.
>>>> You can't sell such a compiler, since source code using any API
>>>> won't be correct.
>>>>
>>>> Please understand that with standardization we're talking about
>>>> supporting the real world.
>>>>
>>>> "Impossible" does not refer to abstract formalism, it refers to the
>>>> real world.
>>>
>>> FWIW, on other platforms - in the real world - "correct" behaviour
>>> is possible. To me this looks like a bug of the windows platform.
>>> long has been the longest word that fits into a register on every
>>> platform I've seen so far. I cannot imagine why you would break this
>>> (unwritten) rule.
>>
>> Too much code based on bad assumptions?
>
> Yes, the reasoning must be something like that.
> But since x86-64 is not binary compatible with x86 and you have to
> recompile in any case, the sensible thing would have been to provide a
> 64 bit version of the platform API where long is really long (i.e. 64
> bit). Problematic code assuming that sizeof(long)=4 is probably only
> found in some low level communication code and that is a bug that
> needs to be fixed anyway. Then, maybe I'm just too naive for the real
> world. ;)
>

From http://msdn.microsoft.com/en-us/library/cc953fe1.aspx there are some
interesting points. First, they announce that by the standard
restrictions (independent of Microsoft):

"long long: Larger than an unsigned long."

This would of course prevent making them same size. Next they go and
standardize for Microsoft C++:

"long, unsigned long: 4 bytes"
"long long: Equivalent to __int64."

Paavo


== 2 of 2 ==
Date: Fri, Jul 24 2009 11:57 pm
From: Ian Collins


Paavo Helde wrote:
>
> From http://msdn.microsoft.com/en-us/library/cc953fe1.aspx there are some
> interesting points. First, they announce that by the standard
> restrictions (independent of Microsoft):
>
> "long long: Larger than an unsigned long."

Where do they get that from? long long isn't even part of the (current)
C++ standard. C99 makes no such statement about the relative size of
unsigned long and long long.

--
Ian Collins


==============================================================================

You received this message because you are subscribed to the Google Groups "comp.lang.c++"
group.

To post to this group, visit http://groups.google.com/group/comp.lang.c++?hl=en

To unsubscribe from this group, send email to comp.lang.c+++unsubscribe@googlegroups.com

To change the way you get mail from this group, visit:
http://groups.google.com/group/comp.lang.c++/subscribe?hl=en

To report abuse, send email explaining the problem to abuse@googlegroups.com

==============================================================================
Google Groups: http://groups.google.com/?hl=en

No comments: