我一直在試驗一個我稱之爲PolymorphicVariant
的類,它非常類似於unique_ptr
,不同之處在於它存儲的是內聯值,而不是分配給堆。爲此,我使用了variant
類型(自制版本)和一些靜態斷言來檢查所有變體是否實現了給定的接口(即它們都來自相同的基類)。然後我有方法得到一個指向基類的指針。然後,我可以將PolymorphicVariant
存儲在容器中,並且它的行爲方式與存儲指向基類的指針相同,除非沒有間接指向。多態變體,並將一個類型的引用綁定到另一個類型的引用
template <typename Base, typename... Derivees>
class PolymorphicVariant {
static_assert(std::is_polymorphic<Base>{},
"Base type has to be polymorphic");
static_assert(meta::And<std::is_base_of<Base, Derivees>...>{},
"Derivees have to derive from Base");
using VariantType = Variant<Derivees...>;
using Types = meta::List<Derivees...>;
struct ToBasePtrVisitor {
template <typename T>
auto operator()(const T& value) const -> const Base* {
return &value;
}
};
public:
// ... Constructors and assignment operators ...
auto get() const -> const Base* {
return apply(ToBasePtrVisitor{}, m_storage);
}
private:
VariantType m_storage;
};
然後我就可以做這樣的東西:
// Bar and Baz both implement IFoo
using Foo = PolymorphicVariant<IFoo, Bar, Baz>;
std::vector<Foo> foos;
for (int i = 0; i < 10; ++i) {
if (i % 2 == 0) {
foos.emplace_back(Bar{});
} else {
foos.emplace_back(Baz{});
}
}
for (const auto& elem : foos) {
elem.get()->some_virtual_fn();
}
所以現在我的問題。比方說,我有一個函數,它的PolymorphicVariant
的引用(就像使用一個函數採用指針抽象基類):
auto mutate_foo(Foo& foo) -> void {
foo.get()->mutating_function();
}
Bar my_bar;
mutate_foo(my_bar); // This doesn't work
這不工作的原因是我不能綁定參考Bar
參考Foo
(即PolymorphicVariant<IFoo, Bar, Baz>
)。有什麼辦法可以做到這一點嗎?某種方式告訴編譯器Bar
參考實際上可以被視爲Foo
參考?無需更改IFoo
或Bar
的實施。如果這是不可能的,我不得不將mutate_foo
的簽名更改爲mutate_foo(IFoo* foo) -> void
,但是這種感覺不那麼幹淨,因爲我希望Foo
能夠像首選類型那樣用來表示「包含滿足要求的東西接口IFoo「。謝謝!
通用接口是'Base'。 'Foo'不是'Bar',因此當函數需要Foo時傳遞一個Bar並不合適。 –
爲什麼不給這個變體隱式地轉換爲基類型,並讓'mutate_foo'也引用基類型? –
我同意Richard的觀點:你可以改變'Foo&foo'來存儲'Baz',而不是提供'Bar my_bar'的調用者。 – dyp