2013-03-17 1 views
2

unique_ptr 인스턴스를 반환하는 함수에 대한 함수 포인터를 만들려고합니다. 각 함수는 많은 호출자에게 일반적으로 유용하기 위해 가능한 한 구체적으로 형식화 된 값을 반환해야합니다 (실제 코드에서는 함수가 생성자 이름 지정되고 각 객체의 공용 헤더에 있음). 그러나이 특정 용도에서는 각 클래스가 구현하는 일반 인터페이스에만 관심이 있습니다.C++을 반환하는 함수 포인터 11 부모 클래스의 unique_ptrs

을 반환하는 함수를 unique_ptr<Superclass>을 반환하는 함수 포인터에 할당 할 수없는 문제가 있습니다.

#include <iostream> 
#include <memory> 

struct Foo { 
    virtual void foo() = 0; 
}; 

struct Bar : public Foo { 
    void foo() {}; 
}; 

std::unique_ptr<Foo> 
foo_creator() 
{ 
    return nullptr; 
} 

std::unique_ptr<Bar> 
bar_creator() 
{ 
    return nullptr; 
} 

typedef std::unique_ptr<Foo>(*creator_fn)(); 

int 
main(int argc, char *argv[]) 
{ 
    std::unique_ptr<Foo> f; 

    f = foo_creator(); 
    f = bar_creator(); 

    creator_fn foo_fn = foo_creator; 
    creator_fn bar_fn = bar_creator; // Fails 

    return 0; 
} 

나는 그 소리에서 얻을 컴파일 오류가 (Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn)) 인 :

cannot initialize a variable of type 'creator_fn' 
(aka 'std::unique_ptr<Foo> (*)()') with an lvalue 
of type 'std::unique_ptr<Bar>()': 

different return type 
('unique_ptr<struct Foo>' vs 'unique_ptr<struct Bar>') 

내가 더 나은 대해 이야기되기 열려있어

나는이 조각까지 내 예를 삶은 한 내 목표를 달성하는 방법. :-)

+1

인가? 'bar_creator'가'Bar'를 생성하면 안됩니까? – Lii

+0

@Lii 이러한 메서드의 내용은 실제로 문제와 관련이 없습니다. 나는 단지'nullptr'을 반환 할 수 있고 같은 문제를 얻을 수 있다고 생각합니다. 큰 코드에서는'Foo'에서 파생 된 클래스가 실제로 두 개 있습니다. 그러나 이것은 더 단순 해 보입니다. - 추가 혼동을 없애기 위해 nullptr이되도록 코드를 편집합니다. – Shepmaster

답변

2

이 코드를 컴파일하는 데 필요한 기능을 유형 인수의 공분산이라고합니다. 주제에 대한 Wikipedia article을 살펴보십시오. 이 작업을 위해

, BarFoo에 하위 유형이 unique_ptr<struct Bar>unique_ptr<struct Foo>에 하위 유형이 될 것이라는 점을 의미 할 것입니다 사실.

일부 언어에는이 속성이 있지만 C++에서는 템플릿과 상속을 함께 사용하는 것이 어렵습니다. 자바에서는이를 작성합니다

UniquePtr<? extends Foo> f; 
f = fooCreator(); 
f = barCreator(); 

UniquePtr<? extends Foo> f는 형식 인수에 공변 인 변수를 선언 곳.

나는 어떤면에서이 문제를 해결하는 디자인을 찾아야한다고 생각한다. This post에는 비슷한 질문이 포함되어있어 도움이 될 수 있습니다.

EDIT : 질문을 잘못 읽고 컴파일 오류가 잘못된 줄로 생각하여 위의 대답이 약간 잘못된 것 같습니다. 나는 여전히 분산의 부족이 문제라고 생각하지만 오류는이 줄에서 발생한다. bar_fn = bar_creator; // Fails

+0

공분산과 관련이 있습니까? 'f = bar_creator()'라인에서'unique_ptr '를 반환하고 아무런 경고없이 'unique_ptr '에 저장합니다. 문제가 발생하는 함수 포인터를 가져올 때만입니다. – Shepmaster

+0

아마도'unique_ptr'는 파생 클래스의 다른'unique_ptr'에서 올바르게 할당 할만큼 똑똑하지만 컴파일 타임 타입 시스템은 ** 공존하지 않는 ** 공분산 문제가됩니까? – Shepmaster

+1

흠, 죄송합니다. 코드를 조금 불편하게 읽은 것 같습니다. 제 대답이 정확하지 않습니다. 나는'f = bar_creator();'라인과'foo_creator'의 리턴 라인 (둘 다 타입 인자가 일치하지 않는 곳)에서 에러를 얻지 못하는 이유를 이해하지 못한다. 나는 C++이 어떤 종류의 분산도 지원하지 않았다는 강한 인상을 받았다. 어쩌면 나는 이것에 대한 질문에 대답하려고 시도 할만큼 충분히 좋은지 모른다 ... – Lii

1

여기는 내 문제를 해결하기 위해 사용 된 수정 된 디자인이다. 새로운 C++ 11 템플릿 using 선언을 사용하여 반환 할 특정 유형을 표시합니다. 내가 함수를 호출 할 때, 나는 아무 문제없이 업 캐스트하는 unique_ptr의 능력을 활용합니다. `표준 : unique_ptr을 (새 바())`: 그것은 그`foo_creator` 모두`bar_creator`이 줄 객체를 만들 의도에 의해

template <class T> 
using creator_fn = std::unique_ptr<T>(*)(); 

int 
main(int argc, char *argv[]) 
{ 
    std::unique_ptr<Foo> f; 

    f = foo_creator(); 
    f = bar_creator(); 

    creator_fn<Foo> foo_fn = foo_creator; 
    creator_fn<Bar> bar_fn = bar_creator; 

    f = foo_fn(); 
    f = bar_fn(); 

    return 0; 
} 
관련 문제