Programing

공개 친구 교환 회원 기능

crosscheck 2020. 6. 10. 08:21
반응형

공개 친구 교환 회원 기능


copy-and-swap-idiom에 대한 아름다운 대답 에는 약간의 도움이 필요한 코드가 있습니다.

class dumb_array
{
public:
    // ...
    friend void swap(dumb_array& first, dumb_array& second) // nothrow
    {
        using std::swap; 
        swap(first.mSize, second.mSize); 
        swap(first.mArray, second.mArray);
    }
    // ...
};

그리고 그는 메모를 추가

우리는 std :: swap을 우리 유형에 특화하고, 무료 기능 스왑과 함께 동급 스왑을 제공해야한다고 주장하는 다른 주장이 있습니다. 그러나 이것은 모두 불필요합니다. 스왑을 올바르게 사용하면 자격이없는 전화를 통해 이루어집니다 우리의 기능은 ADL을 통해 찾을 수 있습니다. 하나의 기능이 수행됩니다.

friend나는 "비우호적 인"조건에 조금 오전, 나는 인정해야합니다. 그래서 내 주요 질문은 다음과 같습니다.

  • 무료 함수처럼 보이지만 클래스 본문 안에 있습니까?
  • swap정적이지 않습니까? 분명히 멤버 변수를 사용하지 않습니다.
  • "스왑을 올바르게 사용하면 ADL을 통해 스왑을 찾을 수 있습니다" ? ADL은 네임 스페이스를 검색 할 것입니다. 그러나 수업 내부에서도 보입니까? 아니면 어디로 friend들어 오나요?

사이드 질문 :

  • C ++ 11에서는 swaps로 표시해야 noexcept합니까?
  • C ++ (11)와 함께 범위-을 위해 , 나는 배치해야합니다 friend iter begin()friend iter end()클래스 내부에 같은 방법은? 나는 friend여기서 필요하지 않다고 생각합니다 .

글을 쓰는 방법은 여러 가지가 있는데 swap, 다른 방법 보다 낫습니다. 그러나 시간이 지남에 따라 단일 정의가 가장 효과적이라는 것이 발견되었습니다. swap함수 작성에 대해 어떻게 생각할 수 있는지 생각해 봅시다 .


먼저 컨테이너와 같은 컨테이너에는 다음과 같은 std::vector<>단일 인수 멤버 함수 swap가 있습니다.

struct vector
{
    void swap(vector&) { /* swap members */ }
};

당연히 우리 수업도 그래야합니까? 글쎄,별로. 표준 라이브러리에는 모든 종류의 불필요한 것들이 있으며 멤버 swap는 그중 하나입니다. 왜? 계속하자.


우리가해야 할 것은 정규 무엇을 파악하고, 우리의 클래스는 무엇을 필요가 그것으로 작업을 할 수 있습니다. 그리고 표준 스와핑 방법은입니다 std::swap. 이것이 멤버 함수가 유용하지 않은 이유입니다. 일반적으로 함수를 바꾸는 방법이 아니고의 동작과 관련이 없습니다 std::swap.

그렇다면 std::swap우리가 일을하려면 std::vector<>전문화를 제공해야하고, 제공해야했을 std::swap까요?

namespace std
{
    template <> // important! specialization in std is OK, overloading is UB
    void swap(myclass&, myclass&)
    {
        // swap
    }
}

이 경우에는 분명히 효과가 있지만 눈에 띄는 문제가 있습니다. 함수 전문화는 부분적으로 불가능합니다. 즉, 우리는 이것으로 템플릿 클래스를 특수화 할 수 없으며 특정 인스턴스화 만 가능합니다.

namespace std
{
    template <typename T>
    void swap<T>(myclass<T>&, myclass<T>&) // error! no partial specialization
    {
        // swap
    }
}

이 방법은 일부 시간에는 작동하지만 항상 작동하지는 않습니다. 더 좋은 방법이 있어야합니다.


있습니다! friend함수 를 사용하고 ADL을 통해 찾을 수 있습니다.

namespace xyz
{
    struct myclass
    {
        friend void swap(myclass&, myclass&);
    };
}

무언가를 교환하고 싶을 때 를 연결 std::swap한 다음 자격이없는 전화를 겁니다.

using std::swap; // allow use of std::swap...
swap(x, y); // ...but select overloads, first

// that is, if swap(x, y) finds a better match, via ADL, it
// will use that instead; otherwise it falls back to std::swap

friend기능 이란 무엇입니까 ? 이 지역에 혼란이 있습니다.

C ++가 표준화되기 전에 friend함수는 "friend name injection" 이라는 기능을 수행했는데 마치 함수가 마치 네임 스페이스에서 작성된 것처럼 코드가 동작 했습니다 . 예를 들어, 이들은 동일한 사전 표준이었습니다.

struct foo
{
    friend void bar()
    {
        // baz
    }
};

// turned into, pre-standard:    

struct foo
{
    friend void bar();
};

void bar()
{
    // baz
}

However, when ADL was invented this was removed. The friend function could then only be found via ADL; if you wanted it as a free function, it needed to be declared as so (see this, for example). But lo! There was a problem.

If you just use std::swap(x, y), your overload will never be found, because you've explicitly said "look in std, and nowhere else"! This is why some people suggested writing two functions: one as a function to be found via ADL, and the other to handle explicit std:: qualifications.

But like we saw, this can't work in all cases, and we end up with an ugly mess. Instead, idiomatic swapping went the other route: instead of making it the classes' job to provide std::swap, it's the swappers' job to make sure they don't use qualified swap, like above. And this tends to work pretty well, as long as people know about it. But therein lies the problem: it's unintuitive to need to use an unqualified call!

To make this easier, some libraries like Boost provided the function boost::swap, which just does an unqualified call to swap, with std::swap as an associated namespace. This helps make things succinct again, but it's still a bummer.

Note that there is no change in C++11 to the behavior of std::swap, which I and others mistakenly thought would be the case. If you were bit by this, read here.


In short: the member function is just noise, the specialization is ugly and incomplete, but the friend function is complete and works. And when you swap, either use boost::swap or an unqualified swap with std::swap associated.


†Informally, a name is associated if it will be considered during a function call. For the details, read §3.4.2. In this case, std::swap normally isn't considered; but we can associate it (add it to the set of overloads considered by unqualified swap), allowing it to be found.


That code is equivalent (in almost every way) to:

class dumb_array
{
public:
    // ...
    friend void swap(dumb_array& first, dumb_array& second);
    // ...
};

inline void swap(dumb_array& first, dumb_array& second) // nothrow
{
    using std::swap; 
    swap(first.mSize, second.mSize); 
    swap(first.mArray, second.mArray);
}

A friend function defined inside a class is:

  • placed in the enclosing namespace
  • automatically inline
  • able to refer to static members of the class without further qualification

The exact rules are in section [class.friend] (I quote paragraphs 6 and 7 of the C++0x draft):

A function can be defined in a friend declaration of a class if and only if the class is a non-local class (9.8), the function name is unqualified, and the function has namespace scope.

Such a function is implicitly inline. A friend function defined in a class is in the (lexical) scope of the class in which it is defined. A friend function defined outside the class is not.

참고URL : https://stackoverflow.com/questions/5695548/public-friend-swap-member-function

반응형