swap
STL 알고리즘 을 활성화하는 적절한 방법은 무엇입니까 ?
1) 회원 swap
. 합니까는 std::swap
멤버를 사용하는 SFINAE의 트릭을 사용합니다 swap
.
2) swap
동일한 네임 스페이스에서 독립형 .
3) std::swap
.
4) 위의 모든 것.
감사합니다.
편집 : 내 질문을 명확하게 말하지 않은 것 같습니다. 기본적으로 템플릿 클래스가 있으며 해당 클래스에 대해 작성한 (효율적인) 스왑 방법을 사용하려면 STL 알고리즘이 필요합니다.
답변
- 의 적절한 사용 입니다
swap
. “라이브러리”코드를 작성하고에서 ADL (인수 종속 조회)을 활성화하려는 경우 이렇게 작성합니다swap
. 또한 이것은 SFINAE와 관련이 없습니다.
// some algorithm in your code
template<class T>
void foo(T& lhs, T& rhs) {
using std::swap; // enable 'std::swap' to be found
// if no other 'swap' is found through ADL
// some code ...
swap(lhs, rhs); // unqualified call, uses ADL and finds a fitting 'swap'
// or falls back on 'std::swap'
// more code ...
}
swap
클래스에 대한 함수 를 제공하는 적절한 방법 입니다.
namespace Foo {
class Bar{}; // dummy
void swap(Bar& lhs, Bar& rhs) {
// ...
}
}
경우 swap
1과 같이 현재)를 사용, 함수가 발견됩니다. 또한 꼭 필요한 경우 해당 함수를 친구로 만들거나 swap
free 함수에 의해 호출되는 멤버 를 제공 할 수 있습니다.
// version 1
class Bar{
public:
friend void swap(Bar& lhs, Bar& rhs) {
// ....
}
};
// version 2
class Bar{
public:
void swap(Bar& other) {
// ...
}
};
void swap(Bar& lhs, Bar& rhs) {
lhs.swap(rhs);
}
...
- 당신은 명시적인 전문화를 의미합니다. Partial은 여전히 다른 것이고 함수에 대해서도 가능하지 않으며 구조체 / 클래스 만 가능합니다. 당신은 전문 수 없기 때문에 이와 같이,
std::swap
템플릿 클래스, 당신은 이 네임 스페이스에 무료 기능을 제공 할 수 있습니다. 내가 그렇게 말할 수 있다면 나쁜 것은 아닙니다. 이제 명시 적 전문화도 가능하지만 일반적으로 함수 템플릿을 전문화하고 싶지 않습니다 .
namespace std
{ // only allowed to extend namespace std with specializations
template<> // specialization
void swap<Bar>(Bar& lhs, Bar& rhs) noexcept {
// ...
}
}
- 아니요, 1)은 2) 및 3)와 구별됩니다. 또한 2)와 3)을 모두 가지고 있으면 더 잘 맞기 때문에 항상 2)가 선택됩니다.
답변
클래스가 템플릿 클래스 일 수있는 EDIT에 응답하려면 전문화가 전혀 필요하지 않습니다. 다음과 같은 클래스를 고려하십시오.
template <class T>
struct vec3
{
T x,y,z;
};
다음과 같은 클래스를 정의 할 수 있습니다.
vec3<float> a;
vec3<double> b;
vec3<int> c;
3 개의 스왑을 모두 구현하는 하나의 함수를 만들 수 있도록하려면 (이 예제 클래스가 보증하는 것은 아님) Xeo가 (2)에서 말한 것처럼 전문화하지 않고 일반 템플릿 함수를 만듭니다.
template <class T>
void swap(vec3<T> &a, vec3<T> &b)
{
using std::swap;
swap(a.x,b.x);
swap(a.y,b.y);
swap(a.z,b.z);
}
스왑 템플릿 함수는 스왑하려는 클래스와 동일한 네임 스페이스에 있어야합니다. 다음 메서드는 ADL을 사용하여 해당 네임 스페이스를 참조하지 않는 경우에도 해당 스왑을 찾아 사용합니다.
using std::swap;
swap(a,b);
답변
네임 스페이스에 선언을 추가하는 것은 일반적으로 정의되지 않은 동작 이기 때문에 (2) ( 사용자 정의 클래스가 선언 된 동일한 네임 스페이스에있는 독립형swap
) 은 사용자 정의 클래스 를 제공 할 수있는 유일한 방법 인 것 같습니다 . 네임 스페이스 std (cppreference.com) 확장 :swap
std
네임 스페이스
std
또는에 중첩 된 네임 스페이스에 선언 또는 정의를 추가하는 것은 정의되지 않은 동작이며std
아래에 몇 가지 예외가 있습니다.
그리고 swap
이러한 예외 중 하나로 표시되지 않습니다. 따라서 네임 스페이스에 자체 swap
오버로드를 추가 std
하는 것은 정의되지 않은 동작입니다.
또한 표준 라이브러리는 이러한 사용자 정의 가 제공되는 경우 사용자 클래스에 대해 사용자 swap
정의를 호출하기 위해 함수에 대한 정규화되지 않은 호출을 사용한다고합니다 .swap
swap
많은 표준 라이브러리 함수 (예 : 많은 알고리즘)는 인수가 Swappable 을 만족할 것으로 예상합니다. 즉, 표준 라이브러리가 스왑을 수행 할 때마다
using std::swap; swap(t, u);
.
(내 표준 라이브러리의 많은 구성 요소
std
호출)swap
에서 비정규 의 사용자 정의 오버로드 : 방식이 아닌 기본 유형의 사용자 정의 오버로드 대신 일반 버전의 호출 할 수 있도록swap
그들이 선택받을 제공되는 유형과 같은 네임 스페이스 선언을 를 통해 인수 의존 검색 이 일반 버전 이상.
그러나 std::swap
사용자 정의 클래스에 대한 함수를 직접 사용하면 사용자 정의 std::swap
대신 일반 버전이 호출 됩니다 swap
.
my::object a, b;
std::swap(a, b); // calls std::swap, not my::swap
따라서 swap
표준 라이브러리에서 수행되는 것과 동일한 방식으로 사용자 코드에서 함수 를 호출하는 것이 좋습니다 .
my::object a, b;
using std::swap;
swap(a, b); // calls my::swap if it is defined, or std::swap if it is not.