我正在尝试为返回unique_ptr
个实例的函数创建函数指针。每个函数都应该返回一个尽可能特定类型的值,以便对许多调用者有用(在我的实际代码中,函数被命名为构造函数,并且在每个对象的公共头文件中)。但是,在这个特定的用法中,我只关心每个类实现的通用接口。
我遇到了一个问题,我无法将返回unique_ptr<Subclass>
的函数分配给返回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;
}
我从clang(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>')
我很乐意被告知更好的方式来实现我的目标。 : - )
答案 0 :(得分:2)
此代码编译所需的功能称为类型参数的协方差。请查看有关该主题的Wikipedia article。
为了实现这一目标,Bar
是Foo
的子类型这一事实必须暗示unique_ptr<struct Bar>
将是unique_ptr<struct Foo>
的子类型。
有些语言有这个属性,但是C ++没有这个属性,因此很难让模板和继承很好地协同工作。在Java中你会写这个:
UniquePtr<? extends Foo> f;
f = fooCreator();
f = barCreator();
其中UniquePtr<? extends Foo> f
声明一个在其类型参数中具有协变性的变量。
我猜你必须找到一种以某种方式解决这个问题的设计。 This post似乎包含了类似的问题,可能会提出一些建议。
编辑:我误解了这个问题并认为编译错误是错误的,所以上面的答案有点误导。我仍然认为缺乏差异是问题,但错误出现在这一行:bar_fn = bar_creator; // Fails
答案 1 :(得分:1)
这是我用来解决我的特定问题的修改设计。我使用新的C ++ 11模板using
声明来标记将返回的特定类型。当我调用该函数时,我利用unique_ptr
的能力进行上传而没有任何问题。
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;
}