Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to choose where function is implemented?

61 views
Skip to first unread message

Öö Tiib

unread,
Nov 23, 2017, 2:49:22 PM11/23/17
to
The C++ developers are different and so some write functions as
members, others as free functions or templates or even
specialize standard library templates.

There must be some trick how to sort that out with code.

How to implement such function template that calls a member
function or if such is not present then function from namespace
of argument or from global namespace or if such is not present
then a function from std namespace?

For motivating example "smart swap" that calls a member swap or
swap from namespace or std::swap. Since the checks are compile
time these will be likely removed by optimizing compiler
(like I comment out in following):

template<typename T>
inline void smart_swap(T& a, T& b)
{
// if (T::swap(T& t) exists)
a.swap(b);
// else if (swap(T& a, T& b) is found) swap(a, b);
// else if (::swap(T& a, T& b) is found) ::swap(a, b);
// else std::swap(a, b);
}

It is sure possible, but how to?

Jorgen Grahn

unread,
Nov 23, 2017, 4:44:16 PM11/23/17
to
On Thu, 2017-11-23, Öö Tiib wrote:
> The C++ developers are different and so some write functions as
> members, others as free functions or templates or even
> specialize standard library templates.

Of course it also depends on the situation: which function you're
implementing.

> There must be some trick how to sort that out with code.
>
> How to implement such function template that calls a member
> function or if such is not present then function from namespace
> of argument or from global namespace or if such is not present
> then a function from std namespace?
>
> For motivating example "smart swap" that calls a member swap or
> swap from namespace or std::swap. Since the checks are compile
> time these will be likely removed by optimizing compiler
> (like I comment out in following):
>
> template<typename T>
> inline void smart_swap(T& a, T& b)
> {
> // if (T::swap(T& t) exists)
> a.swap(b);
> // else if (swap(T& a, T& b) is found) swap(a, b);
> // else if (::swap(T& a, T& b) is found) ::swap(a, b);
> // else std::swap(a, b);
> }
>
> It is sure possible, but how to?

I haven't been paying attention (sorry!) but isn't this what
std::swap() is supposed to take care of?

Or put differently, isn't the author of T responsible for the
performance of std::swap(T&, T&) ?

/Jorgen

--
// Jorgen Grahn <grahn@ Oo o. . .
\X/ snipabacken.se> O o .

Öö Tiib

unread,
Nov 23, 2017, 7:07:54 PM11/23/17
to
On Thursday, 23 November 2017 23:44:16 UTC+2, Jorgen Grahn wrote:
> On Thu, 2017-11-23, Öö Tiib wrote:
> > The C++ developers are different and so some write functions as
> > members, others as free functions or templates or even
> > specialize standard library templates.
>
> Of course it also depends on the situation: which function you're
> implementing.

Yes, that is what I meant. It depends on situation what function
with what data and who is implementing. For example different people
think differently what is better: hash(a) or a.hash() ...
a.to_string() or to_string(a) ... a.clone() or clone(a) ... and so on.

>
> > There must be some trick how to sort that out with code.
> >
> > How to implement such function template that calls a member
> > function or if such is not present then function from namespace
> > of argument or from global namespace or if such is not present
> > then a function from std namespace?
> >
> > For motivating example "smart swap" that calls a member swap or
> > swap from namespace or std::swap. Since the checks are compile
> > time these will be likely removed by optimizing compiler
> > (like I comment out in following):
> >
> > template<typename T>
> > inline void smart_swap(T& a, T& b)
> > {
> > // if (T::swap(T& t) exists)
> > a.swap(b);
> > // else if (swap(T& a, T& b) is found) swap(a, b);
> > // else if (::swap(T& a, T& b) is found) ::swap(a, b);
> > // else std::swap(a, b);
> > }
> >
> > It is sure possible, but how to?
>
> I haven't been paying attention (sorry!) but isn't this what
> std::swap() is supposed to take care of?

Unfortunately no. The std::swap is actually required to be sort of
"usually fine enough" implementation for types that are
move-constructive AND move-assignable and has to be equivalent to
that:

template <class T>
void swap (T& a, T& b)
{
T c(std::move(a)); a=std::move(b); b=std::move(c);
}

> Or put differently, isn't the author of T responsible for the
> performance of std::swap(T&, T&) ?

Each developer (or group of such) may of course agree to take
whatever responsibilities. That does not affect with what library
from what other group they may be need to start integrating their
code next week.

In real code I have seen more often swap(T&, T&) implemented in
namespace of T; less often std::swap(T&, T&) specialized.
However I have seen also T::swap only.

asetof...@gmail.com

unread,
Nov 24, 2017, 3:35:39 AM11/24/17
to
The errors are 2

1) swap has to be called as
. swap(&a,&b)
Because it change the value of a and b and I have to see that
2) swap(&a,&b) has to see if a and b are valid objects analyze their variable for error a->error and b->error if someone is not zero, or a==0 or b==0 store (if possible in the other) in a and b the fail case assign a->error=1 and b->error=1 in case of fail

Juha Nieminen

unread,
Nov 24, 2017, 7:31:41 AM11/24/17
to
Öö Tiib <oot...@hot.ee> wrote:
> For motivating example "smart swap" that calls a member swap or
> swap from namespace or std::swap. Since the checks are compile
> time these will be likely removed by optimizing compiler
> (like I comment out in following):
>
> template<typename T>
> inline void smart_swap(T& a, T& b)
> {
> // if (T::swap(T& t) exists)
> a.swap(b);
> // else if (swap(T& a, T& b) is found) swap(a, b);
> // else if (::swap(T& a, T& b) is found) ::swap(a, b);
> // else std::swap(a, b);
> }
>
> It is sure possible, but how to?

What you are trying to do is compile-time introspection.

C++, at least currently, doesn't really have support for this,
but it can be achieved, to a limited extent, via a relatively
ugly SFINAE kludge. If you google "c++ introspection" you'll
find tutorials.

Ian Collins

unread,
Nov 25, 2017, 6:09:40 PM11/25/17
to
On 11/24/2017 01:07 PM, Öö Tiib wrote:
> On Thursday, 23 November 2017 23:44:16 UTC+2, Jorgen Grahn wrote:
>> On Thu, 2017-11-23, Öö Tiib wrote:
>>> The C++ developers are different and so some write functions as
>>> members, others as free functions or templates or even
>>> specialize standard library templates.
>>
>> Of course it also depends on the situation: which function you're
>> implementing.
>
> Yes, that is what I meant. It depends on situation what function
> with what data and who is implementing. For example different people
> think differently what is better: hash(a) or a.hash() ...
> a.to_string() or to_string(a) ... a.clone() or clone(a) ... and so on.

Just ask yourself whether it makes sense for a to know how to clone its
self or represent its self as a string. For external entity to clone an
object, the object would have to expose too many of its private parts...

--
Ian.

Öö Tiib

unread,
Nov 26, 2017, 2:15:25 PM11/26/17
to
The interface design decisions are usually made long ago by authors
of classes and such decisions seemingly don't depend on answers to the
questions but only on how the authors did perceive what is better
for them to read. That is somewhat understandable. Consider for example
those:

std::ostream& operator<<(std::ostream&, OurType const& val);
std::istream& operator>>(std::istream&, OurType& val);

Now lets ask from ourselves does it make sense for OurType to know how
to stream itself and would not those operators need access to too many
of OurType's private parts? Answers to those questions just can not
matter at all.

0 new messages