내가 인라인 컴파일러를 원하는 A의, B의 등을 함께 수집의 생각과 데이터 중심의 방식으로 그들을 계산하지만, 불행히도 나는 (때문에 알고리즘 우려) 그렇게 할 수있다 이, 열심히.
그건 일어나지 않을 것입니다.
런타임 다형성을 사용 중입니다. 정의에 따라 컴파일러 은 호출 시간에 호출되는을 알 수 없습니다. 수동으로 수행하든 컴파일러에서 수행하든 상관없이 가상 디스패치에 대한 비용을 지불하게됩니다.
인라인은 회원 기능에 대한 호출에 있습니다. 그것은 여전히 "인라인"부분에 도달하기 위해 메모리 액세스 ("유형"가져 오기)를 기반으로 조건부 분기를 수행해야합니다. 그리고 새로 추가 할 때마다 해당 분기에 조건이 추가됩니다. 기껏해야, 이것은 상태 테이블이 될 것입니다 ... 이것은 가상 함수 포인터와 다르지 않습니다 : 메모리 주소에서 가져와 특정 코드 조각으로 분기하는 데 사용합니다.
vtable 포인터처럼 컴파일러가 수행 할 수있는 작업을 구현하는 데 시간을 낭비 할뿐입니다.
프로필 나는 당신의 손으로 작성한 방법이 컴파일러를 능가 할 수 있다고 간단히 가정하는 대신 강력하게 권고합니다. 당신은 언어 수준의 다형성을 포기하기로 결정했습니다 경우
는, 당신은 대신 boost.variant
적절한 방문자를 사용해야합니다. 코드는 다음과 같습니다
typedef boost::variant<A, B> Wrapper;
struct FooVisitor : public boost::static_visitor<>
{
template <typename T> void operator()(T &t) {t.foo()};
};
당신은 당신이 전화를 할 모든 기능에 대한 FooVisitor
을해야 할 것이다.를 호출하려면 다음을 수행하십시오
Wrapper a = existingA;
boost::apply_visitor(FooVisitor(), a);
를 분명히, 당신은 간단한 함수에서 그것을 포장 할 수 있습니다
template<typename Visitor>
void Call(Wrapper &a) {boost::apply_visitor(Visitor(), a);}
:
void CallFoo(Wrapper &a) {boost::apply_visitor(FooVisitor(), a);}
사실, 당신이 이들의 전체 템플릿 가족을 만들 수 있습니다
매개 변수 전달은 허용되지 않습니다 (매개 변수를 방문자 자체에 저장해야 함). 그러나 반환 값을 가질 수 있습니다 (boost::static_visitor<Typename_Here>
visi 선언에 반환 유형을 입력해야 함). 토르).
또한 boost::variant
개체는 값 의미를 가지므로 복사본은 내부 개체를 복사합니다. 실제 유형을 얻으려면 boost::get()
구문을 사용할 수도 있지만 이 실제로이 아닌 경우에는 제안하지 않습니다. 그냥 방문자를 사용하십시오.
'모든 경우를 작성하는 것이 지루하고 오류가 발생하기 쉽습니다.'언어 기능을 삭제하고 직접 코드를 작성하도록 선택하면 어떻게됩니까? 이것이 바로 이러한 언어 기능이 존재하는 이유입니다. 누군가가 상용구를 작성하는 것에 지쳐 있기 때문입니다. –
가상 디스패치를 사용하는 것보다 어떻게 추가 할 수 있습니까? if-else 체인보다는 인덱스 (예 : 배열 조회)로 최적화 된 경우에도 대부분의 컴파일러 구현 측면에서 가상 디스패치를 사용하는 것과 동일합니다. 즉, STATE_X는 vtable을 나타내며 Wrapper :: foo는 vtable 조회와 같습니다. –
사실 가상 함수를 사용하여 직접 구현을 측정 했습니까? 3-5 "if"조건이 가상 함수 호출의 비용과 쉽게 일치 할 수 있습니다. 그리고 함수의 크기가 충분히 커지면 인라인이 실제로 발생한다는 보장은 없습니다 ... –