2009-07-17 2 views
2

그래서 매크로가 있습니다.매크로를 사용하여 std :: swap을 전문적으로 사용할 수 있습니까?

// swap_specialize.hpp 
#include <algorithm> 

#ifndef STD_SWAP_SPECIALIZE 
#define STD_SWAP_SPECIALIZE(CLASSNAME)   \ 
    namespace std {         \ 
    template<> inline        \ 
    void swap(CLASSNAME & lhs, CLASSNAME & rhs) \ 
    { lhs.swap(rhs); } } 
#endif 

그래서 나는 클래스

// c.hpp 
#include <vector> 
#include "swap_specialize.hpp" 
class C 
{ 
    public: 
     C(); 

     void swap(C& rhs) 
     { 
      data_.swap(rhs.data_); 
     } 
     C& operator=(C rhs) 
     { 
      rhs.swap(*this); 
      return *this; 
     } 
    private: 
     std::vector<int> data_; 
} 

STD_SWAP_SPECIALIZE(C) 

이 작업을 수행하기 위해, 문체,이 나쁜 있나요? 코드 냄새입니까? 아니면 괜찮은 연습일까요?

+2

나는 잘 모르겠다. 'c.swap (d);를 수동으로 호출하는 것이 잘못된 이유는 무엇입니까? – GManNickG

+0

나는 동의한다 ... "swap (c, d)"대신 "c.swap (d)"를 호출하기를 원하는 어떤 진짜 이유가 있는가? 단순히 당신이 이전의 "더 좋아 보인다"고 생각하니? 매크로는 일반적으로 좋은 생각이 아니므로 가능하면 ... "#define BEGIN {"및 "#define END}"을 작성한다는 것을 알면 다음 단계로 넘어 가야합니다. – davr

+2

템플릿을 사용 중이고 c.스왑 (d), 그리고 C는 "int"타입을 가지면, 많은 템플릿 에러 메시지가 손실됩니다. –

답변

6

가독성이 높아지면 괜찮다고 말할 수 있습니다. 스스로 판단하십시오. 내 두 센트 : std::swap을 전문으로하는 것은 실제로이 작업을 수행하는 올바른 방법이 아닙니다. 당신이 using std::swap 또는 유사한 무언가를하지 않은 경우

my_stuff::C c, b; 
// ... 
swap(c, b); 
// ... 

std::swap를 찾을 수 없습니다 :이 상황을 생각해 보자. ,

void swap(C &a, C &b) { 
    a.swap(b); 
} 

지금이 위의 경우에도 작동하기 때문에 클래스의 네임 스페이스에 인수 종속 조회 검색 : 당신은 오히려 C의 공간에서 자신의 스왑을 선언해야합니다. 유형이 알 수없는 일반적인 물건을 교환하는 코드는 다음과 같이 그것을 수행해야합니다

using std::swap; 
swap(a, b); 

이 유형에 관계없이, 이것은 가장 일치하는 스왑을 사용, 가을 백을 std::swap에 더 나은이 아니었다면

a의 네임 스페이스에 하나가 일치합니다. std::swap에 대한 호출을 하드 코딩하면 std::swap을 전문으로하지 않고 네임 스페이스에 자체 스왑을 제공하기로 결정하는 유형이 너무 짧아집니다.

이것은 다른 방식으로 대담한 표현입니다. C이 템플릿이라고 상상해보십시오. 이 경우 std::swap을 전문으로 할 수 없습니다. 하지만 스왑을 정의하는 것만으로도 충분합니다.

template<typename T> 
void swap(C<T> &a, C<T> &b) { 
    a.swap(b); 
} 

이렇게하면 std::string 및 다른 클래스의 스왑도 구현되는 방식입니다.

+0

STL 알고리즘은 std :: swap을 사용하지 않습니까? std :: reverse와 같은. – rlbond

+0

std :: swap이 사용되는지 또는 "swap"에 대한 규정되지 않은 호출이 완료되었는지는 지정되지 않았다고 생각합니다. (그래도 참조가 도움이 될 것입니다.) 나는 보았고 gcc는 "스왑"에 대한 부적격 한 호출을 사용합니다. 이것은 클래스의 네임 스페이스에 정의 된 자유 스왑 함수와 잘 작동합니다. 하지만 난 어떤 좋은 표준 lib 구현 "std :: swap"직접 호출하지 않을 것 같아요. 그것은 이상하게 보일 것입니다. 이미 "std"내에 있으므로 자격이 필요하지 않으며, 또 다른 이유 때문에 인수 종속적 인 조회 작업이 중단됩니다. –

+0

당신 말이 맞아요. Section 20.1.4 : Swappable 요구 사항은 다음 조건 중 하나 이상을 충족하여 충족됩니다. - T가 CopyConstructible 요구 사항 (20.1.3) 및 할당 가능 요구 사항 (23.1)을 충족시키는 경우 T는 교체 가능합니다. - Swap이라는 네임 스페이스 범위 함수가 T 정의와 동일한 네임 스페이스에 존재하여 swap (t, u) 표현식이 유효하고 표 32에 설명 된 의미 체계를 가지면 T는 스왑 가능합니다. – rlbond

0

나는 당신에게 많이 사지 않습니다. 템플릿이 아닌 클래스의 경우 매우 적은 수의 선을 저장할 수 있습니다. 그리고 템플릿 클래스의 경우 일반화 (즉, T 모두)하여 전문화하려는 경우에는 작동하지 않습니다.

0

많은 다른 클래스에 STD_SWAP_SPECIALIZE()을 사용한다고 가정 할 때, 저는 이것이 매우 합리적입니다. 결국 그것은 시리즈를 가지고 훨씬 더 읽을 수있어

STD_SWAP_SPECIALIZE(Foo) 
STD_SWAP_SPECIALIZE(Bar) 
STD_SWAP_SPECIALIZE(Baz) 

확장 된 코드보다. 또한 STD_SWAP_SPECIALIZE의 확장이 약간 큰 경우 매크로 정의는 변경이 필요한 경우 단일 위치에서 코드를 제공합니다. (템플릿 정의가 당신의 예제에서 꽤 작기 때문에 그것은 아마 부적절한 포인트 일 것입니다.)

관련 문제