2016-07-25 1 views
0

...가변 클래스/구조체 구조? (노조 템플릿 및하지하지?) 나는 노동 조합을 시도

struct foo 
{ 
    union 
    { 
     struct // 2 bytes 
     { 
      char var0_1; 
     }; 
     struct // 5 bytes 
     { 
      char var1_1; 
      int var1_2; 
     }; 
    }; 
}; 

문제 : 노동 조합 내가 원하는 것을, 그들은 항상 가장 큰 데이터 타입의 크기를 취할 것 제외. 내 경우에는 구조체 foo를 사용하여 아래의 그림처럼 두 구조 중 어느 구조체를 선택해야하는지 알려주는 초기화가 필요합니다. 내가 템플릿과 나는 문자와 INT에 같은 변수 이름을 사용할 수 있다는 사실에 정말 행복했지만 :

그래서 그 후, 나는 ...

template <bool B> 
class foo { } 

template <> 
class foo<true> 
{ 
    char var1; 
} 

template <> 
class foo<false> 
{ 
    char var0; 
    int var1; 
} 

문제를 클래스 템플릿 오버로드를 시도 문제는 문법이었다. 클래스는 컴파일시에 만들어지기 때문에 템플릿 불린 변수는 하드 코딩 된 상수 일 필요가 있지만, 내 경우에는 부울을 런타임에 사용자 정의해야합니다.

그래서 두 개의 "세계"가 필요합니다. 내가 뭘 하려는지 어떻게 성취 할 수 있니?

!! 참고 : foo 클래스/구조체는 나중에 상속 될 것이므로 이미 언급했듯이 foo의 크기가 가장 중요합니다.

수정 # 1 : 응용 프로그램 :

기본적으로이 특정 데이터 버퍼 (인터페이스로의 포인터를 사용하여) 읽기/쓰기 또한 (나 만들 클래스의 새 인스턴스를 허용하는 데 사용됩니다/struct) 동일한 데이터 버퍼. 위에 표시된 변수는 길이를 지정합니다. 크기가 작은 데이터 버퍼 인 경우 길이는 char/byte로 기록됩니다. 더 큰 데이터 버퍼 인 경우 첫 번째 char/byte는 플래그로 null이며 int는 길이를 대신 지정합니다. 길이 이후에는 실제 데이터가 뒤 따른다는 것은 명백합니다. 따라서 상속 이유는 무엇입니까? 클래스의 크기가 가장 중요합니다. 내 케이크 먹고 먹어야 해.

+1

달성하려는 목표는 무엇입니까? – NathanOliver

+1

아마도 boost :: any를 살펴볼 수 있을까요? – AndyG

+0

@ NathanOliver 데이터를 읽거나 쓰는 포인터로 사용하고 새로운 데이터를 쓰도록 인스턴스를 초기화합니다. foo는 더 많은 공유 인터페이스가 될 것입니다. –

답변

0

당신의 해결책은 이해가되지 않습니다. 솔루션에 대해 생각해보십시오 : 두 개의 독립 클래스를 정의 할 수 있습니다 : fooTrue 및 fooFalse와 동일한 결과를 갖는 해당 멤버.

아마, 당신은 상속과 다른 해결책을 찾고있을 것입니다. 예를 들어, fooTrue는 baseFoo이고 fooFalse는 파생 된 Foo를 기본으로 이전 FooFoo와 함께 사용하고 다른 int 멤버로 확장합니다.

이 경우 런타임에 작동하는 메소드로 다형성이 있습니다.

+0

당신은 그 점을 분명히 가지고 있습니다. 나는 한 번해볼 게요. 내가 성취하려고하는 것에 그것을 어떻게 적용 할 수 있는지 보도록하겠습니다. –

0

케이크를 먹을 수는 없습니다.

템플릿의 핵심은 컴파일 타임에 특수화가 발생한다는 것입니다. 런타임에는 클래스의 크기가 고정되어 있습니다 (구현 정의 된 방식 임).

런타임시 선택 사항을 작성하려면 컴파일시 크기를 결정하는 메커니즘을 사용할 수 없습니다. 가능한 두 가지 요구 사항을 충족시키는 메커니즘이 필요합니다. 실질적으로 그것은 기본 클래스가 모든 필수 멤버를 포함 할만큼 충분히 커야한다는 것을 의미합니다. 이는 본질적으로 유니언 기반 솔루션에서 발생합니다.

"!! 참고 사항"을 참조하십시오. 당신이하고있는 것은 조숙 한 최적화의 자격을 얻습니다. 응용 프로그램 (예 : 사용 가능한 메모리를 소모하게 함)에 대해 크기 차이가 실제로 중요하다는 증거가 없으면 기본 클래스의 크기를 최적화하려고합니다.뭔가 다른 클래스의 기본이된다는 사실 자체로는 크기에 대해 걱정할만큼 충분하지 않습니다.

+0

메인 포스트에서 추가 정보를 제공했습니다. –

+0

특정 방식으로 작동하는 프로토콜이 있다고해서 프로그램에서 데이터 구조의 크기를 알아봐야 할 필요는 없습니다. – Peter

1

추상화 계층.

struct my_buffer_view{ 
    std::size_t size()const{ 
    if (!m_ptr)return 0; 
    if (*m_ptr)return *m_ptr; 
    return *reinterpret_cast<std::uint32_t const*>(m_ptr+1); 
    } 
    std::uint8_t const* data() const{ 
    if(!m_ptr)return nullptr; 
    if(*m_ptr)return m_ptr+1; 
    return m_ptr+5; 
    } 
    std::uint8_t const* begin()const{return data();} 
    std::uint8_t const* end()const{return data()+size();} 
    my_buffer_view(std::uint_t const*ptr=nullptr):m_ptr(ptr){} 
    my_buffer_view(my_buffer_view const&)=default; 
    my_buffer_view& operator=(my_buffer_view const&)=default; 
private: 
    std::uint8_t const* m_ptr=0; 
}; 

어디서나 크기가 가변적 인 데이터가 없습니다.

struct header{ 
    std::uint8_t short_len; 
    union { 
     struct{ 
     std::uint32_t long_len; 
     std::uint8_t long_buf[1]; 
     } 
     struct { 
     std::short_buf[1]; 
     } 
    } body; 
    }; 

을하지만 난 그냥 대신 포인터 연산을했다 : 나는 size ETX의 조합을 사용했다 coukd.

이러한 버퍼를 바이트 스트림에 기록하는 것은 완전히 다른 문제입니다.

+0

이 방법은 정확한 케이스에 도움이되지 않지만 코드의 좋은 부분이며보다 일반적인 경우에는 도움이 될 것입니다. 당신의 기여에 감사드립니다. –

관련 문제