Topic: Why there are both complex::real and std::real?


Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Tue, 3 Nov 2009 12:26:59 CST
Raw View
On 2 Nov., 04:26, "Joe Smith" <unknown_kev_...@hotmail.com> wrote:

[..]

> I also have some namespacing concerns with free functions. Free functions
> can be used in two different ways. I'll show these by example.
>
> namespace complex_utils{
> template<typename T>
> T conj(T& t)
> { return T(std::real(t), -std::imag(t)); }
> }
>
> That sort of does not cause namespace issues. When I define my new
> complex-like type that is comaptible enough that many templates designed for
> std::complex can use it, I simply inject a new overload into namespace std,
> which I am explicitly permitted to do.

Nope, your are not permitted to do that. The only thing you could
do without violating the standard is to provide specializations
of real and imag for a user-defined type, [namespace.std]/1:

"[..] A program may add a template specialization for any standard
library template to namespace std only if the declaration depends
on a user-defined type of external linkage and the specialization
meets the standard library requirements for the original template
and is not explicitly prohibited."

There exists no permission regarding adding overloads to
namespace std and the truncated first sentence of
[namespace.std]/1 is very strict here:

"The behavior of a C++ program is undefined if it adds declarations
or definitions to namespace std or to a namespace within
namespace std unless otherwise specified.[..]"

> The other form is as follows.
>
> namespace soemthing{
> template<typename T>
> T conj(const T& t)
> { return T(real(t), -imag(t)); }
> }

A slightly better version is

  namespace soemthing{
  template<typename T>
  T conj(const T& t)
  {
     using std::real;
     using std::imag;
     return T(real(t), -imag(t)); }
  }

and ensuring that both free functions are in scope during
instantiation.

HTH & Greetings from Bremen,

Daniel Kr   gler




--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: frege <gottlobfrege@gmail.com>
Date: Tue, 3 Nov 2009 12:26:59 CST
Raw View
On Nov 1, 10:26 pm, "Joe Smith" <unknown_kev_...@hotmail.com> wrote:
>
> I also have some namespacing concerns with free functions. Free functions
> can be used in two different ways. I'll show these by example.
>
> namespace complex_utils{
> template<typename T>
> T conj(T& t)
> { return T(std::real(t), -std::imag(t)); }
>
> }
>
> That sort of does not cause namespace issues. When I define my new
> complex-like type that is comaptible enough that many templates designed for
> std::complex can use it, I simply inject a new overload into namespace std,
> which I am explicitly permitted to do.
>
> The other form is as follows.
>
> namespace soemthing{
> template<typename T>
> T conj(const T& t)
> { return T(real(t), -imag(t)); }
>
> }
>
> Here, ADL is being used. Injecting an overload into namespace std will do
> nothing here, since the compiler will be looking in my namespace for real
> and imag. Thus in some sense, now I need a my_ns::real(my_complex) function,
> when it is conceptually an overload of std::real, and thus ought to belong
> there. In some sense then my namespace is being infringed upon. I would not
> be objecting to the infringment upon the ::my_ns::my_complex namespace of
> member functions, since my goal is compaibilty, but infringing the ::my_ns
> namespace so that ::my_ns::my_complex can be compatible seems wrong.
>

template<typename T>
T conj(const T& t)
{
    using namespace std;

    return T(real(t), -imag(t));
}

I've seen this form a few times (if I recall it correctly),
particularly for swap() which is sometimes injected into std::,
sometimes not, depending on implementor.
I think this then catches both cases, favouring the T version of real
()/imag() if it exists (via ADL).

I agree with you that, in general, the right thing to do is to
overload std::real(), as that is the context of what you are
implementing.  Otherwise a function like real(t) could be anything -
not related to complex numbers at all...

Tony


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Joe Smith" <unknown_kev_cat@hotmail.com>
Date: Fri, 6 Nov 2009 23:39:49 CST
Raw View
"Daniel Kr   gler" <daniel.kruegler@googlemail.com> wrote:
> On 2 Nov., 04:26, "Joe Smith" <unknown_kev_...@hotmail.com> wrote:
>>
>> That sort of does not cause namespace issues. When I define my new
>> complex-like type that is comaptible enough that many templates designed
>> for
>> std::complex can use it, I simply inject a new overload into namespace
>> std,
>> which I am explicitly permitted to do.
>
> Nope, your are not permitted to do that. The only thing you could
> do without violating the standard is to provide specializations
> of real and imag for a user-defined type, [namespace.std]/1:
>
> "[..] A program may add a template specialization for any standard
> library template to namespace std only if the declaration depends
> on a user-defined type of external linkage and the specialization
> meets the standard library requirements for the original template
> and is not explicitly prohibited."

I was aware of this case, but was under the impression that overloads for
user defined types were also permitted. The underlying logic being the same.
I suppose that would not be needed if all functions where adding an overload
for a user defined type could  be useful are actually function templates, so
roughly the same thing could be accomplished with adding a specialization.



--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr= FCgler?= <daniel.kruegler@googlemail.com>
Date: Tue, 27 Oct 2009 17:26:53 CST
Raw View
On 27 Okt., 20:14, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
> On Oct 27, 12:26 am, Daniel Kr   gler <daniel.krueg...@googlemail.com>
> wrote:
> So, the free functions real() and imag() are there just for C/C++
> compatibility.

Yes, exactly.

> For new abstractions let say run-time rational numbers, we don't need
> to such compatibility, because there is no rational number related functions
> in C, then we don't have to worry about these things. Right?

This is correct.

HTH & Greetings from Bremen,

Daniel Kr   gler




--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Joe Smith" <unknown_kev_cat@hotmail.com>
Date: Fri, 30 Oct 2009 12:31:18 CST
Raw View
"Daniel Kr= FCgler" <daniel.kruegler@googlemail.com> wrote in message
news:aa2d0be1-e9fd-431d-a495-a5adc2b947ed@h40g2000prf.googlegroups.com...

    On 27 Okt., 20:14, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:

        On Oct 27, 12:26 am, Daniel Kr   gler <daniel.krueg...@googlemail.com>
        wrote:
        So, the free functions real() and imag() are there just for C/C++
        compatibility.


    Yes, exactly.

        For new abstractions let say run-time rational numbers, we don't need
        to such compatibility, because there is no rational number
related functions
        in C, then we don't have to worry about these things. Right?


    This is correct.


That does imply that it would be better to use the member functions in
templates than the free functions, since other complex-like classes
that the template may be useful for are likely to have the member
functions, but not free function overloads, right?


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Fri, 30 Oct 2009 14:31:44 CST
Raw View
On 30 Okt., 19:31, "Joe Smith" <unknown_kev_...@hotmail.com> wrote:
> "Daniel Kr= FCgler" <daniel.krueg...@googlemail.com> wrote in messagenews:aa2d0be1-e9fd-431d-a495-a5adc2b947ed@h40g2000prf.googlegroups.com...
>
>     On 27 Okt., 20:14, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
>
>         On Oct 27, 12:26 am, Daniel Kr   gler <daniel.krueg...@googlemail.com>
>         wrote:
>         So, the free functions real() and imag() are there just for C/C++
>         compatibility.
>
>     Yes, exactly.
>
>         For new abstractions let say run-time rational numbers, we don't need
>         to such compatibility, because there is no rational number
> related functions
>         in C, then we don't have to worry about these things. Right?
>
>     This is correct.
>
> That does imply that it would be better to use the member functions in
> templates than the free functions, since other complex-like classes
> that the template may be useful for are likely to have the member
> functions, but not free function overloads, right?

I don't know whether a clear answer to that question exists,
it depends on whether there is a commonly accepted
concept of a complex type. Another perspective to the
same problem is that especially complex types are typically
near to built-in types (in C they are built-in's) and this
may cause implementors to develop them such that no
need for a class type exists. This kind of thinking has
a long tradition in C++ and if you check out the last draft
for decimal support in C++

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2009/n2849.pdf

you will observe that the chosen interface corresponds to
non-class types or in other words: If the decimal type is
implemented as non-class type you won't notice the difference
if the type is used "normally", e.g. by not attempting to call
operators explicitly. From this POV I would expect that
third-party implementations of a complex type would
tend to use the same strategy and would provide non-member
functions of the real and imag observers as well. The same
idiom can be recognized by observing that basically no abs
function is realized as a member function. One could also
say that it might have been not such a good idea that
std::complex did provide real and imag as member functions
at all, because they are somewhat redundant in the
presence of the free observer functions.

Returning to your question: I don't expect that a template
code for complex-like types would necessarily attempt
to get access to the real and imaginary part of the number
by member functions. But a library might consider to use
SFINAE tricks to determine whether access is possible by
member functions and otherwise might attempt to fall-back
to the free function access (or vice versa).

HTH & Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: frege <gottlobfrege@gmail.com>
Date: Sat, 31 Oct 2009 00:58:44 CST
Raw View
>
> That does imply that it would be better to use the member functions in
> templates than the free functions, since other complex-like classes
> that the template may be useful for are likely to have the member
> functions, but not free function overloads, right?
>

The general trend I'm seeing (for all templates, not just things like
complex) is to use free functions.  That way, your template can cover
all types - even those without member functions.  Because I can always
add free functions, but I can't always add member functions (ie to
classes that aren't 'mine', etc).

And you can also add a default free impl that calls the member impl:

template <typename T> double real(T t)
{
    return t.real();
}

If TheComplexImUsing has a real() member function, I don't do
anything.  If it doesn't, then I implement a specialized real
(TheComplexImUsing) function.

Tony


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: "Joe Smith" <unknown_kev_cat@hotmail.com>
Date: Sun, 1 Nov 2009 21:26:58 CST
Raw View
"frege" <gottlobfrege@gmail.com> wrote in message
news:1858197e-a472-4036-8716-bf96f5a0bb34@k4g2000yqb.googlegroups.com...
> >
>> That does imply that it would be better to use the member functions in
>> templates than the free functions, since other complex-like classes
>> that the template may be useful for are likely to have the member
>> functions, but not free function overloads, right?
>>
>
> The general trend I'm seeing (for all templates, not just things like
> complex) is to use free functions.  That way, your template can cover
> all types - even those without member functions.  Because I can always
> add free functions, but I can't always add member functions (ie to
> classes that aren't 'mine', etc).
>

And here again we get back to the classic debate of what belongs as member
functions of a class and what belongs as free functions. In many cases, for
those who understand basic OO concepts, member functions often syntacticly
make more sense than free functions. Microsoft's Intellesense system, and
others like it make it easier to use member functions when available.

There are however a few big problems with member functions. One is that
those functions that really do not benefit from having direct access to
private members have such access anyway. For code maintenence reasons, it is
usually preferable if only functions that need such acess have it, so that
fewer functions actually use the private members, making it far easier to
change them later if needed. Obviously, there is a tradeoff here, and needs
is somewhat subjective. If a function can be implemented without acess, but
it is far more complicated than if it had access to the private members,
then perhaps it should have that access, etc.

If there were a nice way to make pseudo-member functions that did not have
private acess, that would aleviate the problem. It may also potentially
aleviate the other problem, that third party extentions cannot add member
functions without using inheirtance. This is both good and bad. On one hand
letting everybody inject additional functions as member functions sounds
like it would become problematic, as all such functions are effectively in
the same namespace. But it prevents third parties from adding new functions
access like member functions even if they syntactically would make sense as
them.

When I first heard of the concept proposal, I was under the impression that
at least for deduced contexts this problem could be solved. I was under the
impression that except for some operators, all functions in a concept would
be pseudo-member functions, becoming calls to the real member function or to
the definition in the concept_map. This made good sense to me. through this
mechanism, one could add pseudo-member functions to any existing class, or
even to built-in types, and things would just work, at least in contrained
contexts. But apparently others seem to think that many functions in
concepts should be pseudo-free functions instead, mapping to the real free
function, or to the definition in the concept_map as applicable.

I also have some namespacing concerns with free functions. Free functions
can be used in two different ways. I'll show these by example.

namespace complex_utils{
template<typename T>
T conj(T& t)
{ return T(std::real(t), -std::imag(t)); }
}

That sort of does not cause namespace issues. When I define my new
complex-like type that is comaptible enough that many templates designed for
std::complex can use it, I simply inject a new overload into namespace std,
which I am explicitly permitted to do.

The other form is as follows.

namespace soemthing{
template<typename T>
T conj(const T& t)
{ return T(real(t), -imag(t)); }
}

Here, ADL is being used. Injecting an overload into namespace std will do
nothing here, since the compiler will be looking in my namespace for real
and imag. Thus in some sense, now I need a my_ns::real(my_complex) function,
when it is conceptually an overload of std::real, and thus ought to belong
there. In some sense then my namespace is being infringed upon. I would not
be objecting to the infringment upon the ::my_ns::my_complex namespace of
member functions, since my goal is compaibilty, but infringing the ::my_ns
namespace so that ::my_ns::my_complex can be compatible seems wrong.

Even a template that autocalls member functions being present in namespace
std would not prevent the polluting of ::my_ns, since that template function
would never even be considered if ADL style is being used.


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Saeed Amrollahi <amrollahi.saeed@gmail.com>
Date: Mon, 26 Oct 2009 13:14:23 CST
Raw View
Dear experts
Hello

I have a question about complex numbers in standard library. Why there
are both complex::real/imag
member functions and std::real/imag global funcctions? consider:
complex<double> cd(1,2);
double r = cd.real();
r = real(cd);
double i  = cd.imag();
i = imag(cd);

>From point of OO view, it is obvious the real() and imag() should be
part of member functions.
What is the benefit of global ones?

Thanks,
 -- Saeed Amrollahi

--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: =?ISO-8859-1?Q?Daniel_Kr=FCgler?= <daniel.kruegler@googlemail.com>
Date: Mon, 26 Oct 2009 15:26:52 CST
Raw View
On 26 Okt., 20:14, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
> I have a question about complex numbers in standard library. Why there
> are both complex::real/imag
> member functions and std::real/imag global funcctions? consider:
> complex<double> cd(1,2);
> double r = cd.real();
> r = real(cd);
> double i  = cd.imag();
> i = imag(cd);
>
> >From point of OO view, it is obvious the real() and imag() should be
>
> part of member functions.
> What is the benefit of global ones?

The member functions are natural for a language with classes, like
C++, therefore the member functions exist. The free function real
and imag exist to match the free functions of C99 in their *generic*
forms from 7.22 <tgmath.h>. With C++0x on all generic C99 complex
functions will have a pendant in <complex> (Nearly all: fabs is
missing
because of LWG defect 595).

HTH & Greetings from Bremen,

Daniel Kr   gler


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]





Author: Saeed Amrollahi <amrollahi.saeed@gmail.com>
Date: Tue, 27 Oct 2009 13:14:34 CST
Raw View
On Oct 27, 12:26 am, Daniel Kr   gler <daniel.krueg...@googlemail.com>
wrote:
> On 26 Okt., 20:14, Saeed Amrollahi <amrollahi.sa...@gmail.com> wrote:
>
> > I have a question about complex numbers in standard library. Why there
> > are both complex::real/imag
> > member functions and std::real/imag global funcctions? consider:
> > complex<double> cd(1,2);
> > double r = cd.real();
> > r = real(cd);
> > double i  = cd.imag();
> > i = imag(cd);
>
> > >From point of OO view, it is obvious the real() and imag() should be
>
> > part of member functions.
> > What is the benefit of global ones?
>
> The member functions are natural for a language with classes, like
> C++, therefore the member functions exist. The free function real
> and imag exist to match the free functions of C99 in their *generic*
> forms from 7.22 <tgmath.h>. With C++0x on all generic C99 complex
> functions will have a pendant in <complex> (Nearly all: fabs is
> missing
> because of LWG defect 595).
>
> HTH & Greetings from Bremen,
>
> Daniel Kr   gler
>
> --
> [ comp.std.c++ is moderated.  To submit articles, try just posting with ]
> [ your news-reader.  If that fails, use mailto:std-...@netlab.cs.rpi.edu]
> [              --- Please see the FAQ before posting. ---               ]
> [ FAQ:http://www.comeaucomputing.com/csc/faq.html                     ]

Hi Daniel
Thank you for your feedback.

So, the free functions real() and imag() are there just for C/C++
compatibility.
For new abstractions let say run-time rational numbers, we don't need
to such
compatibility, because there is no rational number related functions
in C, then
we don't have to worry about these things. Right?

Thanks in advance,
 -- Saeed Amrollahi


--
[ comp.std.c++ is moderated.  To submit articles, try just posting with ]
[ your news-reader.  If that fails, use mailto:std-c++@netlab.cs.rpi.edu]
[              --- Please see the FAQ before posting. ---               ]
[ FAQ: http://www.comeaucomputing.com/csc/faq.html                      ]