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:
Post a Comment