Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.c++ > #119544 > unrolled thread

How to implement Foo:swap

Started bywij <wyniijj5@gmail.com>
First post2024-06-28 01:42 +0800
Last post2024-07-20 20:18 -0700
Articles 20 on this page of 42 — 8 participants

Back to article view | Back to comp.lang.c++


Contents

  How to implement Foo:swap wij <wyniijj5@gmail.com> - 2024-06-28 01:42 +0800
    Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-27 19:53 +0200
      Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-27 19:57 +0200
    Re: How to implement Foo:swap red floyd <no.spam.here@its.invalid> - 2024-06-27 14:02 -0700
      Re: How to implement Foo:swap wij <wyniijj5@gmail.com> - 2024-06-28 08:51 +0800
        Re: How to implement Foo:swap red floyd <no.spam.here@its.invalid> - 2024-06-27 21:46 -0700
        Re: How to implement Foo:swap red floyd <no.spam.here@its.invalid> - 2024-06-27 21:53 -0700
        Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-28 11:04 -0700
    Re: How to implement Foo:swap Paavo Helde <eesnimi@osa.pri.ee> - 2024-06-28 00:04 +0300
    Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-27 22:21 -0700
      Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-28 10:16 +0200
        Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-28 09:33 -0700
          Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-28 23:51 +0200
            Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-28 15:23 -0700
              Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 12:12 +0200
                Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 15:03 +0200
                  Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 08:59 -0700
                    Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 19:04 +0200
                      Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 10:27 -0700
                        Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 19:52 +0200
                      Re: How to implement Foo:swap "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2024-06-29 12:33 -0700
                        Re: How to implement Foo:swap "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2024-06-29 12:34 -0700
                        Re: How to implement Foo:swap Richard Damon <richard@damon-family.org> - 2024-06-29 16:13 -0400
                          Re: How to implement Foo:swap "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2024-06-29 13:52 -0700
                        Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-30 00:38 +0200
                          Re: How to implement Foo:swap "Chris M. Thomasson" <chris.m.thomasson.1@gmail.com> - 2024-06-29 18:09 -0700
                    Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 19:22 +0200
                      Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 10:43 -0700
                        Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 19:49 +0200
                          Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 11:03 -0700
                            Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 20:08 +0200
                              Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 11:24 -0700
                                Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 20:46 +0200
                                  Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 20:48 -0700
                Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 08:55 -0700
                  Re: How to implement Foo:swap Bonita Montero <Bonita.Montero@gmail.com> - 2024-06-29 19:05 +0200
                    Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 10:35 -0700
                Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-06-29 09:15 -0700
      Re: How to implement Foo:swap Marcel Mueller <news.5.maazl@spamgourmet.org> - 2024-07-15 20:33 +0200
        Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-07-15 20:04 -0700
          Re: How to implement Foo:swap Marcel Mueller <news.5.maazl@spamgourmet.org> - 2024-07-20 13:19 +0200
            Re: How to implement Foo:swap Andrey Tarasevich <andreytarasevich@hotmail.com> - 2024-07-20 20:18 -0700

Page 2 of 3 — ← Prev page 1 [2] 3  Next page →


#119578

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2024-06-29 12:33 -0700
Message-ID<v5pni5$2b21$4@dont-email.me>
In reply to#119566
On 6/29/2024 10:04 AM, Bonita Montero wrote:
> Am 29.06.2024 um 17:59 schrieb Andrey Tarasevich:
>> On 06/29/24 6:03 AM, Bonita Montero wrote:
>>> And usually I place the swap-code into the std-namespace, specialized
>>> for my custom data structure so that if so explicitly uses std::swap
>>> this still works.
>>
>> A very ugly idea.
> 
> It's not ugly because std::swap will never be specialized for my own
> datastructure in the global namespace. And you can be assured that if
> someone uses std::swap prefixed on your own data structure that this
> works.
[...]

Injecting anything into the std namesapce is bad. ;^o

> 

[toc] | [prev] | [next] | [standalone]


#119579

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2024-06-29 12:34 -0700
Message-ID<v5pnjt$2b21$5@dont-email.me>
In reply to#119578
On 6/29/2024 12:33 PM, Chris M. Thomasson wrote:
> On 6/29/2024 10:04 AM, Bonita Montero wrote:
>> Am 29.06.2024 um 17:59 schrieb Andrey Tarasevich:
>>> On 06/29/24 6:03 AM, Bonita Montero wrote:
>>>> And usually I place the swap-code into the std-namespace, specialized
>>>> for my custom data structure so that if so explicitly uses std::swap
>>>> this still works.
>>>
>>> A very ugly idea.
>>
>> It's not ugly because std::swap will never be specialized for my own
>> datastructure in the global namespace. And you can be assured that if
>> someone uses std::swap prefixed on your own data structure that this
>> works.
> [...]
> 
> Injecting anything into the std namesapce is bad. ;^o
> 
>>
> 

namespace std
{
    // add things
}

No! Bad mojo.

[toc] | [prev] | [next] | [standalone]


#119580

FromRichard Damon <richard@damon-family.org>
Date2024-06-29 16:13 -0400
Message-ID<v5ppu2$1gd9d$1@i2pn2.org>
In reply to#119578
On 6/29/24 3:33 PM, Chris M. Thomasson wrote:
> On 6/29/2024 10:04 AM, Bonita Montero wrote:
>> Am 29.06.2024 um 17:59 schrieb Andrey Tarasevich:
>>> On 06/29/24 6:03 AM, Bonita Montero wrote:
>>>> And usually I place the swap-code into the std-namespace, specialized
>>>> for my custom data structure so that if so explicitly uses std::swap
>>>> this still works.
>>>
>>> A very ugly idea.
>>
>> It's not ugly because std::swap will never be specialized for my own
>> datastructure in the global namespace. And you can be assured that if
>> someone uses std::swap prefixed on your own data structure that this
>> works.
> [...]
> 
> Injecting anything into the std namesapce is bad. ;^o
> 
>>
> 

But the Standard SPECIFICALLY allows for it, as long as the Injected 
item is a specialization/overload of a defined thing using a user 
defined type in the specialization/overload.

[toc] | [prev] | [next] | [standalone]


#119581

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2024-06-29 13:52 -0700
Message-ID<v5ps6a$3csi$1@dont-email.me>
In reply to#119580
On 6/29/2024 1:13 PM, Richard Damon wrote:
> On 6/29/24 3:33 PM, Chris M. Thomasson wrote:
>> On 6/29/2024 10:04 AM, Bonita Montero wrote:
>>> Am 29.06.2024 um 17:59 schrieb Andrey Tarasevich:
>>>> On 06/29/24 6:03 AM, Bonita Montero wrote:
>>>>> And usually I place the swap-code into the std-namespace, specialized
>>>>> for my custom data structure so that if so explicitly uses std::swap
>>>>> this still works.
>>>>
>>>> A very ugly idea.
>>>
>>> It's not ugly because std::swap will never be specialized for my own
>>> datastructure in the global namespace. And you can be assured that if
>>> someone uses std::swap prefixed on your own data structure that this
>>> works.
>> [...]
>>
>> Injecting anything into the std namesapce is bad. ;^o
>>
>>>
>>
> 
> But the Standard SPECIFICALLY allows for it, as long as the Injected 
> item is a specialization/overload of a defined thing using a user 
> defined type in the specialization/overload.

I, personally, do not like to do that.

[toc] | [prev] | [next] | [standalone]


#119582

FromBonita Montero <Bonita.Montero@gmail.com>
Date2024-06-30 00:38 +0200
Message-ID<v5q2de$4m2s$1@raubtier-asyl.eternal-september.org>
In reply to#119578
Am 29.06.2024 um 21:33 schrieb Chris M. Thomasson:
> On 6/29/2024 10:04 AM, Bonita Montero wrote:
>> Am 29.06.2024 um 17:59 schrieb Andrey Tarasevich:
>>> On 06/29/24 6:03 AM, Bonita Montero wrote:
>>>> And usually I place the swap-code into the std-namespace, specialized
>>>> for my custom data structure so that if so explicitly uses std::swap
>>>> this still works.
>>>
>>> A very ugly idea.
>>
>> It's not ugly because std::swap will never be specialized for my own
>> datastructure in the global namespace. And you can be assured that if
>> someone uses std::swap prefixed on your own data structure that this
>> works.
> [...]
> 
> Injecting anything into the std namesapce is bad. ;^o

Not if the specialization doesn't collide with the namespace's
definitions.

[toc] | [prev] | [next] | [standalone]


#119583

From"Chris M. Thomasson" <chris.m.thomasson.1@gmail.com>
Date2024-06-29 18:09 -0700
Message-ID<v5qb7c$67h8$2@dont-email.me>
In reply to#119582
On 6/29/2024 3:38 PM, Bonita Montero wrote:
> Am 29.06.2024 um 21:33 schrieb Chris M. Thomasson:
>> On 6/29/2024 10:04 AM, Bonita Montero wrote:
>>> Am 29.06.2024 um 17:59 schrieb Andrey Tarasevich:
>>>> On 06/29/24 6:03 AM, Bonita Montero wrote:
>>>>> And usually I place the swap-code into the std-namespace, specialized
>>>>> for my custom data structure so that if so explicitly uses std::swap
>>>>> this still works.
>>>>
>>>> A very ugly idea.
>>>
>>> It's not ugly because std::swap will never be specialized for my own
>>> datastructure in the global namespace. And you can be assured that if
>>> someone uses std::swap prefixed on your own data structure that this
>>> works.
>> [...]
>>
>> Injecting anything into the std namesapce is bad. ;^o
> 
> Not if the specialization doesn't collide with the namespace's
> definitions.
> 

If a team I was working with is doing it, I would say, uggg, okay! Let's 
go. However, personally, I don't like to inject things into the std 
namespace.

[toc] | [prev] | [next] | [standalone]


#119568

FromBonita Montero <Bonita.Montero@gmail.com>
Date2024-06-29 19:22 +0200
Message-ID<v5pfst$14il$1@raubtier-asyl.eternal-september.org>
In reply to#119564
Now it works:

#include <iostream>

using namespace std;

template<typename T>
struct Foo
{
private:
	T m_val;
	template<typename T2>
	friend void swap( Foo<T2> &lhs, Foo<T2> &rhs ) noexcept;
};

template<typename T>
void swap( Foo<T> &lhs, Foo<T> &rhs ) noexcept
{
	T t = lhs.m_val;
	lhs.m_val = rhs.m_val;
	rhs.m_val = t;
}

int main()
{
	Foo<string> fsA, fsB;
	::swap( fsA, fsB );
}

The only disadvantage with the code is that all swaps for different Ts /
T2s can access the m_val in Foo.

I've got no problem to inject a swap into std unless it is only
specified for std't types.

[toc] | [prev] | [next] | [standalone]


#119571

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 10:43 -0700
Message-ID<v5ph47$13e5$3@dont-email.me>
In reply to#119568
On 06/29/24 10:22 AM, Bonita Montero wrote:
> Now it works:
> 
> #include <iostream>
> 
> using namespace std;
> 
> template<typename T>
> struct Foo
> {
> private:
>      T m_val;
>      template<typename T2>
>      friend void swap( Foo<T2> &lhs, Foo<T2> &rhs ) noexcept;
> };
> 
> template<typename T>
> void swap( Foo<T> &lhs, Foo<T> &rhs ) noexcept
> {
>      T t = lhs.m_val;
>      lhs.m_val = rhs.m_val;
>      rhs.m_val = t;
> }
> 
> int main()
> {
>      Foo<string> fsA, fsB;
>      ::swap( fsA, fsB );
> }
> 
> The only disadvantage with the code is that all swaps for different Ts /
> T2s can access the m_val in Foo.
> 
> I've got no problem to inject a swap into std unless it is only
> specified for std't types.

Here it is. Now you finally managed to provide a in-class friend 
declaration that properly matches the out-of-class definition.

* Firstly, this has a lot more syntactic clutter.

* Secondly, as you already noted, it grants unnecessary cross-friendship 
(this second problem can be solved (by adding a bit more clutter).

Now compare it with mine

   template<typename T>
   struct Foo
   {
   private:
     T m_val;

     friend void swap(Foo &lhs, Foo &rhs) noexcept
     {
       T t = lhs.m_val;
       lhs.m_val = rhs.m_val;
       rhs.m_val = t;
     }
   };

This is a lot cleaner.

Now, I'm not a big fan of multiline in-class member definitions. But, as 
I said above, this `swap` cannot be defined out-of-class. The language 
has no syntax for it.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#119572

FromBonita Montero <Bonita.Montero@gmail.com>
Date2024-06-29 19:49 +0200
Message-ID<v5phel$1d3f$1@raubtier-asyl.eternal-september.org>
In reply to#119571
Am 29.06.2024 um 19:43 schrieb Andrey Tarasevich:

> * Firstly, this has a lot more syntactic clutter.

I think my soulution is more readable and the declarative add-on doesn't
hurt.

> 
> * Secondly, as you already noted, it grants unnecessary cross-friendship 
> (this second problem can be solved (by adding a bit more clutter).

That's a theoretical problem.

> Now compare it with mine
> 
>    template<typename T>
>    struct Foo
>    {
>    private:
>      T m_val;
> 
>      friend void swap(Foo &lhs, Foo &rhs) noexcept
>      {
>        T t = lhs.m_val;
>        lhs.m_val = rhs.m_val;
>        rhs.m_val = t;
>      }
>    };
> 
> This is a lot cleaner.

For me absolutely not because I like out-of-class definitions which
make the class itself more readable. Usually classes are much longer
that this counts.

> Now, I'm not a big fan of multiline in-class member definitions. But, as 
> I said above, this `swap` cannot be defined out-of-class. The language 
> has no syntax for it.

I've shown the syntax.

[toc] | [prev] | [next] | [standalone]


#119574

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 11:03 -0700
Message-ID<v5pi8q$1esa$1@dont-email.me>
In reply to#119572
On 06/29/24 10:49 AM, Bonita Montero wrote:
> 
> I've shown the syntax.
> 

Apparently there's no hope...

You've shown the syntax for *template* `swap`. Meanwhile, I'm stating 
that there's no syntax for defining a *non-template* `swap` out-of-class.

See the difference?

We are talking about two completely different things. Yes, it is a 
rather intricate and dark corner of C++ semantics, but I hoped you'd 
grasp it by now.

Here's a little educational example for you (for GCC, since it uses 
`__PRETTY_FUNCTION__`)

   #include <iostream>

   template <typename T> struct S
   {
     friend void foo(S &)
       { std::cout << __PRETTY_FUNCTION__ << std::endl; }
   };

   template <typename T> void bar(S<T> &)
     { std::cout << __PRETTY_FUNCTION__ << std::endl; }

   int main()
   {
     S<int> s;
     foo(s);
     bar(s);
   }

The code outputs the follwing

   void foo(S<int>&)
   void bar(S<T>&) [with T = int]

   https://coliru.stacked-crooked.com/a/3fccf6372dfe21e7

Now, the little detail I want to draw your attention to is what 
`__PRETTY_FUNCTION__` outputs for these two functions. See that `[...]` 
part in the `bar`s output? Wonder why it is missing in the `foo`s output?

In our original `swap` problem I want a `foo`-like `swap`, not 
`bar`-like. I want a solution that has no `[...]` in the 
`__PRETTY_FUNCTION__`.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#119575

FromBonita Montero <Bonita.Montero@gmail.com>
Date2024-06-29 20:08 +0200
Message-ID<v5pij4$1kdr$1@raubtier-asyl.eternal-september.org>
In reply to#119574
Am 29.06.2024 um 20:03 schrieb Andrey Tarasevich:
> On 06/29/24 10:49 AM, Bonita Montero wrote:
>>
>> I've shown the syntax.
>>
> 
> Apparently there's no hope...
> 
> You've shown the syntax for *template* `swap`. ...

That's a sufficient solution for the same thing.

[toc] | [prev] | [next] | [standalone]


#119576

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 11:24 -0700
Message-ID<v5pjh0$1pq0$1@dont-email.me>
In reply to#119575
On 06/29/24 11:08 AM, Bonita Montero wrote:
> Am 29.06.2024 um 20:03 schrieb Andrey Tarasevich:
>> On 06/29/24 10:49 AM, Bonita Montero wrote:
>>>
>>> I've shown the syntax.
>>>
>>
>> Apparently there's no hope...
>>
>> You've shown the syntax for *template* `swap`. ...
> 
> That's a sufficient solution for the same thing.

It is. But that's not the issue I was talking about.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#119577

FromBonita Montero <Bonita.Montero@gmail.com>
Date2024-06-29 20:46 +0200
Message-ID<v5pkp9$21dn$1@raubtier-asyl.eternal-september.org>
In reply to#119576
Am 29.06.2024 um 20:24 schrieb Andrey Tarasevich:
> On 06/29/24 11:08 AM, Bonita Montero wrote:
>> Am 29.06.2024 um 20:03 schrieb Andrey Tarasevich:
>>> On 06/29/24 10:49 AM, Bonita Montero wrote:
>>>>
>>>> I've shown the syntax.
>>>>
>>>
>>> Apparently there's no hope...
>>>
>>> You've shown the syntax for *template* `swap`. ...
>>
>> That's a sufficient solution for the same thing.
> 
> It is. But that's not the issue I was talking about.

For me this issue doesn't exist because I know a solution
with issues that don't hurt.

[toc] | [prev] | [next] | [standalone]


#119584

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 20:48 -0700
Message-ID<v5qkj8$bfb3$1@dont-email.me>
In reply to#119577
On 06/29/24 11:46 AM, Bonita Montero wrote:
> Am 29.06.2024 um 20:24 schrieb Andrey Tarasevich:
>> On 06/29/24 11:08 AM, Bonita Montero wrote:
>>> Am 29.06.2024 um 20:03 schrieb Andrey Tarasevich:
>>>> On 06/29/24 10:49 AM, Bonita Montero wrote:
>>>>>
>>>>> I've shown the syntax.
>>>>>
>>>>
>>>> Apparently there's no hope...
>>>>
>>>> You've shown the syntax for *template* `swap`. ...
>>>
>>> That's a sufficient solution for the same thing.
>>
>> It is. But that's not the issue I was talking about.
> 
> For me this issue doesn't exist because I know a solution
> with issues that don't hurt.

That's fine.

In general case (also implying that we'll need non-public access), there 
are three ways to define a friend to a template class

1. Non-template friend

     template <typename T> class C
     {
       int i;
       friend void foo(C &c) { c.i = 42; }
     };

   The definition has to be done in-class.

2. Template friend with loose friendship

     template <typename T> class C
     {
       int i = 0;
       template <typename U> friend void foo(C<U> &c) { c.i = 42; }
     };

   The definition can be done in-class or out-of-class.

3. Template friend with strict friendship

     template <typename> class C;
     template <typename T> void foo(C<T> &);

     template <typename T> class C
     {
       int i = 0;
       friend void foo<>(C &);
     };

     template <typename T> void foo(C<T> &c) { c.i = 42; }

   The definition can only be done out-of-class, if I'm not mistaken.

You apparently prefer #2. I prefer #1.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#119563

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 08:55 -0700
Message-ID<v5paqg$3vvn7$1@dont-email.me>
In reply to#119561
On 06/29/24 3:12 AM, Bonita Montero wrote:
> Am 29.06.2024 um 00:23 schrieb Andrey Tarasevich:
> 
>> As I already stated above, the language provides no other syntax for 
>> achieving this objective besides the one based on `friend`.
> 
> Works:
> 
> #include <iostream>
> 
> using namespace std;
> 
> template<typename T>
> struct Foo
> {
>      T m_val;
>      friend void swap( Foo &lhs, Foo &rhs ) noexcept;
> };
> 
> template<typename T>
> void swap( Foo<T> &lhs, Foo<T> &rhs ) noexcept
> {
>      T t = lhs.m_val;
>      lhs.m_val = rhs.m_val;
>      rhs.m_val = t;
> }
> 

Um...

Firstly, your code is not doing what you think it is doing. The `friend` 
declaration in the class has no relation to the template declaration 
outside the class. (Try making the members `private` and you'll 
immediately see that your template has no access to them.)

The `friend` declaration plays no role whatsoever in your code. It is 
not used at all. You can simply remove it - it won't change anything.

Secondly, you implemented `swap` as a separate template. Which is a 
completely different thing from what I wanted. I don't want a separate 
template. I want (and I repeat): a *non-template* `swap` function to be 
automatically emitted by compiler for each specialization of `Foo<>`.

Mine is a completely different approach. And, (and I repeat) this can 
only be done through a `friend` hack I described above.

-- 
Best regards,
Andrey

[toc] | [prev] | [next] | [standalone]


#119567

FromBonita Montero <Bonita.Montero@gmail.com>
Date2024-06-29 19:05 +0200
Message-ID<v5pesq$uo3$2@raubtier-asyl.eternal-september.org>
In reply to#119563
Am 29.06.2024 um 17:55 schrieb Andrey Tarasevich:
> On 06/29/24 3:12 AM, Bonita Montero wrote:
>> Am 29.06.2024 um 00:23 schrieb Andrey Tarasevich:
>>
>>> As I already stated above, the language provides no other syntax for 
>>> achieving this objective besides the one based on `friend`.
>>
>> Works:
>>
>> #include <iostream>
>>
>> using namespace std;
>>
>> template<typename T>
>> struct Foo
>> {
>>      T m_val;
>>      friend void swap( Foo &lhs, Foo &rhs ) noexcept;
>> };
>>
>> template<typename T>
>> void swap( Foo<T> &lhs, Foo<T> &rhs ) noexcept
>> {
>>      T t = lhs.m_val;
>>      lhs.m_val = rhs.m_val;
>>      rhs.m_val = t;
>> }
>>
> 
> Um...
> 
> Firstly, your code is not doing what you think it is doing. ...

My own swap is called; I've tried that in the debugger.

[toc] | [prev] | [next] | [standalone]


#119570

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 10:35 -0700
Message-ID<v5pgl3$13e5$2@dont-email.me>
In reply to#119567
On 06/29/24 10:05 AM, Bonita Montero wrote:
> My own swap is called; I've tried that in the debugger.

Yes, it is called. But what point are you trying to make?

As I stated many times previously: my objective is to provide a 
dedicated *non-template* `swap` for each specialization of `Foo<>`. And 
I demonstrated how one can do that (through an in class `friend` 
definition).

Your code provides a *template* `swap`. This is a completely different 
approach for solving the same problem.

I like my approach better.

There are objective reasons why it is better, but let's just take it as 
my caprice for now. I just want a *non-template* `swap`.

-- 
Best regards,
Andrey




[toc] | [prev] | [next] | [standalone]


#119565

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-06-29 09:15 -0700
Message-ID<v5pbuo$8qn$1@dont-email.me>
In reply to#119561
On 06/29/24 3:12 AM, Bonita Montero wrote:
> 
> Without :: before swap this doesn't work.
> 

This is actually what should have made you realize that your in-class 
`friend` declaration and your out-of-class template `swap` declaration 
are completely unrelated.

Without the `::`, the ADL finds the `friend` version of `swap`. The 
unqualified lookup prefers that `friend` version. So, it calls it. 
However, the `friend` version is not defined in your code. So, you end 
up with a linker error.

And, as I said above, you can't define it out-of-class. The language 
provides no syntax for out-of-class definition of such friends. You can 
only do it inline, exactly as I do in my code sample.

-- 
Best regards,
Andrey


[toc] | [prev] | [next] | [standalone]


#119626

FromMarcel Mueller <news.5.maazl@spamgourmet.org>
Date2024-07-15 20:33 +0200
Message-ID<v73q1s$g1at$1@gwaiyur.mb-net.net>
In reply to#119554
Am 28.06.24 um 07:21 schrieb Andrey Tarasevich:
> Firstly, when implementing a custom `swap` for your custom type it is a 
> better idea to implement it as a friend function

Sometimes it can be useful to have a swap member function.
E.g. when implementing assignment functions/operators the pattern
   Foo(whatever_arguments).swap(*this);
cannot be simply converted to a free swap function because the 
constructor does does not bind the the reference argument. You always 
need a named variable in this case.

> A friend-based implementation will allow one to use your type with the 
> `using std::swap` idiom.

?


Marcel

[toc] | [prev] | [next] | [standalone]


#119630

FromAndrey Tarasevich <andreytarasevich@hotmail.com>
Date2024-07-15 20:04 -0700
Message-ID<v74o0k$13bsj$2@dont-email.me>
In reply to#119626
On 07/15/24 11:33 AM, Marcel Mueller wrote:
> Am 28.06.24 um 07:21 schrieb Andrey Tarasevich:
>> Firstly, when implementing a custom `swap` for your custom type it is 
>> a better idea to implement it as a friend function
> 
> Sometimes it can be useful to have a swap member function.
> E.g. when implementing assignment functions/operators the pattern
>    Foo(whatever_arguments).swap(*this);
> cannot be simply converted to a free swap function because the 
> constructor does does not bind the the reference argument. You always 
> need a named variable in this case.

This is an old and a well-known asymmetry in how overloaded operators 
behave in C++. And fixing this asymmetry is actually one of the 
side-applications of rvalue references in C++11.

Before C++11 the problem you described could also be observed in the 
following example

   #include <string>
   #include <fstream>

   int main()
   {
     std::string hello = "Hello";
     std::ofstream("text.txt") << hello << 123 << std::endl; // 1
     std::ofstream("text.txt") << 123 << hello << std::endl; // 2
   }

Lines 1 and 2 look very similar. However, line 1 triggers an error 
before C++11, while line 2 compiles fine.

`operator <<` for `std::string` is overloaded by a standalone function, 
which expects `std::ostream &` (a non-const lvalue reference) as its 
first parameter. This immediately means that a temporary object cannot 
be used as its argument. For this reason sub-expression 
`std::ofstream("text2.txt") << hello` is already invalid.

Meanwhile, line 2 is valid even in C++98. In this case a member overload 
of `operator <<` for `int` argument is invoked first. There's no 
restrictions on invoking non-const member functions for temporaries. 
That invocation returns a `std::ostream &`, which can then be 
successfully used as an argument for `operator <<` for `std::string`. 
So, in this case the initial `<<` for `int` saves the day as an 
accidental "rvalue-to-lvalue" converter.

In C++11 an additional template overload for `<<` has been added to the 
library (see [ostream.rvalue])

   template <class charT, class traits, class T>
     basic_ostream<charT, traits>&
       operator<<(basic_ostream<charT, traits>&& os, const T& x);

which simply does `os << x`, thus taking up the role of rvalue-to-lvalue 
converter. Line 1 above becomes valid in C++11.

-- 
Best regards,
Andrey




[toc] | [prev] | [next] | [standalone]


Page 2 of 3 — ← Prev page 1 [2] 3  Next page →

Back to top | Article view | comp.lang.c++


csiph-web