2013-03-18 2 views
3

조건부 멤버로 구조체를 만들려고합니다. 즉, 다른 멤버는 특정 전문화 영역에만 존재합니다. 그러나 나는이 수업이 가능한 한 가장 빠르길 원한다.C++ 11 : 조건부 컴파일 : 구성원

방법 1 :

template<typename T, bool with_int = false> 
struct foo 
{ 
    template<typename... Args> 
    foo(Args&&... args) : m_t(forward<Args>(args)...) 
    {} 

    T m_t; 
} 

template<typename T> 
struct foo<T, true> 
{ 
    template<typename... Args> 
    foo(Args&&... args) : m_t(forward<Args>(args)...), m_id(0) 
    {} 

     T m_t; 
     int m_id; 
}; 
  • Disadventage : 나는 3 개의 differents 방법을 시도했습니다 각 전문 분야에 대한 코드를 반복했다.

방법 2 :

template<typename T, bool with_int = false> 
struct foo 
{ 
    template<typename... Args> 
    foo(Args&&... args) : m_t(forward<Args>(args)...) 
    {} 

    virtual ~foo() {} 

    T m_t; 
} 

template<typename T> 
struct foo<T, false> : public foo<T> 
{ 
     using foo<T>::foo; 

     int m_id = 0; 
}; 
  • Adventage : 몇 가지 코드입니다.
  • Disadventage : vtables/상속 사용/etc : 구성 또는 구성원 액세스에 시간이 더 걸립니까? 그러나 다른면에서는 기본 클래스에 "참조"를 사용하는 척하지 않습니다. 이 aproach의 실제 모험이나 불이익은 무엇입니까?

방법 3

using nil_type = void*; 
using zero_type = nil_type[0]; 

template<typename T, bool with_int = false> 
struct foo 
{ 
    template<typename... Args, typename = typename enable_if<with_int>::type> 
    foo(Args&&... args) : m_t(forward<Args>(args)...), m_int(0) 
    {} 

    template<typename... Args, typename = typename enable_if<!with_int>::type> 
    foo(Args&&... args) : m_t(forward<Args>(args)...) 
    {}   

    T m__t; 
    typename conditional<with_int, int, zero_type>::type m_int; 
}; 
  • Ventages : 한 번 코드를 작성; with_intfalse 일 때 필드 m_int의 크기는 0입니다 (거의 gcc 4.7.2).
  • Adventages : 템플릿을 많이 사용하여 (가독성을 떨어 뜨림) 컴파일러가 크기 0의 멤버를 처리하는 방법에 대해 확신하지 못합니다. 실제로 크기 0 필드가 위험하거나 의미가 어느 정도인지는 알 수 없습니다. 반복되는 생성자이지만, 아마도 이것은 피할 수 있습니다.

가장 좋은 방법이나 방법은 무엇입니까?

+0

OT,하지만 두 개의 밑줄이 포함 된 이름은 컴파일러 용으로 예약되어 있으므로 m_int와 m_t로 가야합니다. – filmor

+0

회원들에게 ** 밑줄을 두 번 붙인 것으로 생각하지만 그것을 포함하지는 않습니다. –

+5

아니, 대답 [여기] (http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-ac-identifier) ​​참조하십시오 :'들어있는 각 이름 이중 밑줄 (_ _) 또는 밑줄 문자 (2.11)로 시작하는 밑줄 문자로 시작하는 문자는 어떤 용도로든 구현에 사용됩니다. – filmor

답변

4

상속을 고려하셨습니까?

+0

내 두 번째 시도에서 상속 사용이 고려됩니다.읽어주십시오. 제 질문은 아래에 있습니다. –

+1

당신의 접근 방식이 다르고,'가상'(비용이 듭니다)를 사용하며, int-case를 non-int-case에서 파생하려고 시도합니다.이 경우는 IMHO가 상황을 더 복잡하게 만들고 명확한 분리를 제공하지 않습니다. 그러나 그것은 단지 나의 제안 일 뿐이며, 이것이 당신에게 효과가 있는지 알 수 없습니다. –

+0

올바른 해결책입니다. 'foo_int_base '의 _additional_ 크기는 0입니다 (확실히 최적화 된 빌드에서). 구성원과 달리 기본 클래스 하위 개체의 크기는 0 일 수 있습니다. – MSalters