문제

내 상황에서 사용하는 것이 무엇인지, 그 이유를 알고 싶습니다. 우선 RTTI (typeid)를 사용하는 것이 나쁘다고 들었습니다. 누구든지 이유를 설명 할 수 있습니까? 정확히 유형을 알고 있다면 런타임에서 비교하는 것이 무엇입니까? 또한 boost :: type_of를 사용하는 방법이 있습니까? 나는 Mighty Google을 통해 검색하는 것을 발견하지 못했습니다 :) 나를위한 다른 솔루션은 전문화이지만, 적어도 9 가지 유형의 새로운 방법을 전문화 할 것입니다. 다음은 필요한 예입니다.

이 수업이 있습니다

  template<typename A, typename B, typename C>
  class CFoo
  {
     void foo()
     {
       // Some chunk of code depends on old A type
     }

  }

그래서 나는 TypeID를 확인하고 (내가 들었던 것은 나쁘다) 다음과 같은 예 에서이 3 가지 실현을해야합니다.

 void foo()
   {
      if (typeid(A) == typeid(CSomeClass)
       // Do this chunk of code related to A type
      else
      if (typeid(B) == typeid(CSomeClass)
       // Do this chunk of code related to B type
      else
      if (typeid(C) == typeid(CSomeClass)
       // Do this chunk of code related to C type
   }

그렇다면 최상의 솔루션은 무엇입니까? 모든 유형에는 3 개의 전문화가 있기 때문에 모든 A, B, C를 전문화하고 싶지는 않습니다. 따라서 9 가지 방법을 얻 거나이 TypeID 확인을받을 수 있습니다.

도움이 되었습니까?

해결책

때문에 나쁘다

  1. A, B 및 C는 컴파일 타임에서 알려져 있지만 런타임 메커니즘을 사용하고 있습니다. TypeId를 호출하면 컴파일러는 메타 데이터를 객체 파일에 포함시켜야합니다.
  2. "유형과 관련된이 코드 덩어리"를 CSOMECLASS의 인터페이스를 사용하는 실제 코드로 바꾸면 A! = CSOMECLASS 및 호환되지 않는 인터페이스가있는 경우 코드를 컴파일 할 수 없습니다. 컴파일러는 코드가 실행되지 않더라도 여전히 코드를 번역하려고합니다. (아래 예제 참조)

일반적으로하는 것은 코드를 별도의 기능 템플릿 또는 전문화 할 수있는 클래스의 정적 멤버 기능으로 고려하는 것입니다.

나쁜:

template<typename T>
void foo(T x) {
    if (typeid(T)==typeid(int*)) {
        *x = 23; // instantiation error: an int can't be dereferenced
    } else {
        cout << "haha\n";
    }
}
int main() {
    foo(42); // T=int --> instantiation error
}

더 나은:

template<typename T>
void foo(T x) {
    cout << "haha\n";
}
void foo(int* x) {
    *x = 23;
}
int main() {
    foo(42); // fine, invokes foo<int>(int)
}

건배, s

다른 팁

일반적으로 RTTI없이 솔루션을 제시 할 수 있습니다. 그것은 당신이 소프트웨어의 디자인을 올바르게 생각하지 않았다는 것을 보여줄 수 있습니다. 그건 나빠. 때때로 RTTI ~할 수 있다 그래도 좋은 일이 되십시오.

그럼에도 불구하고 당신이하고 싶은 일에는 이상한 것이 없습니다. 다음과 같이 설계된 임시 템플릿을 만들 수 없습니까?

template< class T > class TypeWrapper
{
  T t;
public:
  void DoSomething()
  {
  }
};

그런 다음 다음과 같이 원하는 기능을 부분적으로 전문화하십시오.

template<> class TypeWrapper< CSomeClass >
{
  CSomeClass c;
public:
  void DoSomething()
  {
     c.DoThatThing();
  }
};

그런 다음 수업에서 위의 정의에서 당신은 ...와 같은 일을 할 것입니다.

주형

  class CFoo
  {
     TypeWrapper< A > a;
     TypeWrapper< B > b;
     TypeWrapper< C > c;
     void foo()
     {
       a.DoSomething();
       b.DoSomething();
       c.DoSomething();
     }

  }

이런 식으로 부분적으로 특수한 템플릿을 통과하는 경우 실제로 "dosomething"호출에서 무언가를 수행합니다.

문제는 모든 전문화에 대해 쓰는 코드 덩어리에 있습니다.

글을 쓰면 상관 없습니다 (길이로)

void foo()
{
   if (typeid(A) == typeid(CSomeClass)
    // Do this chunk of code related to A type
   else
   if (typeid(B) == typeid(CSomeClass)
    // Do this chunk of code related to B type
   else
   if (typeid(C) == typeid(CSomeClass)
    // Do this chunk of code related to C type
}

또는

void foo()
{
   A x;
   foo_( x );
   B y;
   foo_( y );
   C z;
   foo_( z );
}
void foo_( CSomeClass1& ) {}
void foo_( CSomeClass2& ) {}
void foo_( CSomeClass3& ) {}

두 번째 사례의 상승점은 클래스 D를 추가 할 때 컴파일러에 써야 할 FOO_ 누락에 대한 오버로드가 있음을 상기시키는 것입니다. 이것은 첫 번째 변형에서 잊을 수 있습니다.

나는 이것이 처음에 작동하지 않을까 걱정됩니다. 유형이 csomeclass가 아닌 경우에도 "코드 청크"는 컴파일 할 수 있어야합니다.

나는 type_of가 도움이 될 것이라고 생각하지 않습니다 (C ++ 0x의 Auto 및 Decltype와 동일하다면).

이 세 덩어리를 별도의 기능으로 추출하고 Csomeclass에 대해 각각 과부하 할 수 있다고 생각합니다. (편집 : 오, 거기 있습니다 else if's. 그러면 실제로 많은 과부하/전문화가 필요할 수 있습니다. 이 코드는 무엇입니까?)

edit2 : 코드가 다음과 동등한 일을하기를 희망하는 것으로 보입니다. 여기서 int는 특수 유형입니다.

#include <iostream>

template <class T>
bool one() {return false; }

template <>
bool one<int>() { std::cout << "one\n"; return true; }

template <class T>
bool two() {return false; }

template <>
bool two<int>() { std::cout << "two\n"; return true; }

template <class T>
bool three() {return false; }

template <>
bool three<int>() { std::cout << "three\n"; return true; }

template <class A, class B, class C>
struct X
{
    void foo()
    {
        one<A>() || two<B>() || three<C>();
    }
};

int main()
{
    X<int, double, int>().foo(); //one
    X<double, int, int>().foo();  //two
    X<double, double, double>().foo(); //...
    X<double, double, int>().foo(); //three
}

어딘가에 추상화가 잘못되었다고 생각합니다.

나는 그들이 노출시키는 데 필요한 인터페이스 측면에서 A, B & C를 재정의하려고 시도합니다 (순수한 가상 방법을 사용한 C ++의 추상 기본 클래스).

템플릿은 기본적으로 오리 유형을 허용하지만 CFOO는 AB & C 클래스에 대해 너무 많이 알고있는 것처럼 들립니다.

typeid는 다음과 같이 나쁘다.

  1. TypeId는 비싸고 부풀어 오른 바이너리, 필요하지 않은 추가 정보를 제공합니다.
  2. 모든 컴파일러가 지원하는 것은 아닙니다
  3. 기본적으로 클래스 계층 구조를 깨고 있습니다.

권장하는 것은 리팩토링입니다. 템플릿을 제거하고 대신 A, B & C의 인터페이스를 정의하고 CFOO가 해당 인터페이스를 가져 오도록하십시오. 이렇게하면 A, B & C가 실제로 응집력있는 유형이되도록 동작을 리팩터링해야합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top