2017-12-13 42 views
2

현재 C# 버전의 ANTLR4에서 C++ 타겟으로 일부 코드를 이식하고 있으며 현재 일부 문제가 있습니다. 내가 C#에서 AST를 작성한 방법은 기본 클래스 (Base라고 부름)와 파생 클래스 (파생 클래스라고 함)를 생성하고 클래스를 구현하는 데 사용할 수있는 가상 함수를 작성하는 것이 었습니다.antlrcpp :: Any에서 Base 클래스 가져 오기

그러나이 코드를 C++로 변환하려고하면 bad_cast 예외가 발생합니다. 파생 클래스를 기본 클래스로 올바르게 캐스팅하지 않은 경우 antlrcpp :: Any로 제한했습니다. 예를 들어 :

class Base { 
public: 
    virtual std::string ToString() const { return "Base\n"; } 
}; 

class Derived : public Base { 
public: 
    std::string ToString() const override { return "Derived\n"; } 
}; 

int main() { 
    Derived value; 
    std::cout << value.ToString(); //Obviously prints out Derived 
    Base& base_value = value; 
    std::cout << base_value.ToString(); //Still works exactly as expected and prints Derived 

    auto any = antlrcpp::Any(value); 
    auto derived = any.as<Base>(); //internally uses a dynamic_cast and throws a bad_cast 
    std::cout << derived.ToString(); //never gets to here 
} 

그러나 그것을, 나는 처음에 그것은 단지 포인터와 함께 일하기 때문에 내가 헤더 내부 static_castdynamic_cast을 변경하지만, 어쩌면

auto any = antlrcpp::Any(new Derived()); 
std::cout << any.as<Base*>()->ToString(); //throws bad_cast 

라고 생각하고 그것을 던져 것 "Base"를 출력합니다. 또한 C 스타일 캐스팅은 데이터 멤버가 액세스 할 때 크래시를 유발합니다.

antlrcpp::Any을 정확히 사용하여 기본 클래스를 얻으려면 어떻게해야합니까? 내가 놓친 게 분명해?

그리고 이것이 가능하지 않은 경우 어떻게해야합니까? .is() 메서드가 있지만 방문자의 반환 값을 확인하기위한 검사가 특정 유형에 불과한 경우가 많습니다 (예 : 표현식 사용시 30-40 연산자가있을 수 있음).

+0

가능한 복제본 : [C++ 이기종 컨테이너, 형식으로 항목 가져 오기] (https://stackoverflow.com/questions/47768354/c-heterogeneous-container-get-entry-as-type). 'Base'에서 파생 된 객체를 저장해야하는 경우,'Base * '를 저장할 수 있으며 검색시 필요한 유형으로 동적 캐스트 할 수 있습니다. –

+0

별도의 질문을하는 것이 반드시 중복되는 것은 아닙니다. 그러나 그 해결책은 여기에 적용되는 것처럼 보입니다. 'antlrcpp : Any ((Base *) value)'와'any.as ()'는 Derived 클래스를 올바르게 리턴합니다. antlrcpp :: Any가 unique_ptr을 지원하지 않아 메모리를 관리해야하므로 조금 실망 스럽습니다. 다른 방법으로 복사 할 수 있습니다. – Thatguypat

답변

1

antlrcpp::any 클래스는 이러한 종류의 시나리오에 대해서는 작성되지 않습니다. 보편적 인 Variant 구현이 아닙니다.

필요하다면 유형 삭제와 작동하지 않는 다양한 유형에 대해 합집합을 사용하여 자신의 Variant 구현에 대해 생각해야합니다.

고유 포인터는 복사 문법을 지원하지 않으므로 일반적으로이 컨텍스트에서는 좋지 않습니다 (여기에서 필요합니다). 방문자를 평가할 때는 shared_ptr으로 대신 방문하십시오.

+0

댓글과이 답변을 결합하면 잘됩니다. 'shared_ptr '을 사용하고 모든 파생물을'Base '로 형변환하면 원시 포인터를 사용하는 기억 문제를 해결하고 완벽하게 작동합니다. 내 자신의 variant 클래스를 구현하는 것이 왜 필요한지 알 수 없습니다. – Thatguypat