考虑一下:
struct Base {
static Base make() { return {}; }
};
struct Derived {
// I _would_ want to have a `static Derived make()` automagically here
};
解决上述问题的一种方法是
struct Base {
template <typename Self>
static Self make() { return {}; }
};
struct Derived {
static constexpr auto make = Base::make<Derived>;
};
,但它不会在重载的情况下工作,而且我do需要它在重载的情况下工作......
还有更好的选择吗?
不幸的是,不可能做你想做的事情,但有一些替代方案,具体取决于你在代码中的实际目标。
首先要注意的是,重载静态方法并不是那么有趣,因为无论如何你只能使用静态分派来调用它,这几乎违背了除了代码组织之外的要点。演示您是否有以下代码(并且
magic_type
以某种方式存在)。
struct Base {
static magic_type make() { return {}; }
};
struct Derived : public Base {
static magic_type make() { return {}; }
};
然后您必须将这些方法调用为
Base::make()
和 Derived::make()
。如果这是可以接受的,那么我建议使用模板专业化。
template <typename T>
T make(){
return T();
}
template <>
Base make<Base>(){
return Base();
}
template <>
Derived make<Derived>(){
return Derived();
}
可能在某个名称空间中,以避免与其他名为
make
的内容发生冲突。然后调用此代码将是 make<Base>()
或 make<Derived>()
,这在灵活性方面几乎相同。
如果你真正想要的是重写
make
方法,并且想要动态调度(这意味着不使函数静态),那么它仍然不太可能。您可以使用名称遮蔽来获取看起来大致正确的代码,但这是不好的做法,并且可能不会执行您想要的操作(我避免添加示例,因为它不应该执行并且无论如何也不会给您动态调度) 。或者,您可以返回一个指针,这可能是最接近您的目标的解决方案。
struct Base {
std::unique_ptr<Base> make() {
return std::make_unique<Base>();
}
};
struct Derived : public Base {
std::unique_ptr<Base> make() {
return std::unique_ptr((Base*)(new (std::nothrow) Derived()));
}
};
几乎可以肯定有一种更好的方法来创建 Derived,但目前已经足够好了。
这绝对与您最初的请求不同,并且考虑到您的实际目标,这可能是不可接受的,但我希望这两种可能的解决方案之一适合您,或者至少提示您找到适合您的特定用例的解决方案。