因为以下是非法的:
struct A {
template <typename T>
virtual T* foo() = 0;
};
struct B : A {
template <typename T>
virtual T* foo() override {return new T;} // Simple example here.
};
template <typename T>
T* bar (A* a) {
return a->foo<T>(); // The need for the virtual method.
}
并且模板只出现在返回类型中,我想到了使用重载的(天真?)解决方法:
#include <iostream>
struct Base { virtual void show() const = 0; };
struct Object : Base { virtual void show() const override {std::cout << "I am an Object.\n";} };
struct Thing : Base { virtual void show() const override {std::cout << "I am a Thing.\n";} };
struct Blob : Base { virtual void show() const override {std::cout << "I am a Blob.\n";} };
struct A {
virtual Object* foo (Object&&) = 0;
virtual Thing* foo (Thing&&) = 0;
virtual Blob* foo (Blob&&) = 0;
};
struct B : A {
virtual Object* foo (Object&&) override {return fooHelper<Object>();}
virtual Thing* foo (Thing&&) override {return fooHelper<Thing>();}
virtual Blob* foo (Blob&&) override {return fooHelper<Blob>();}
private:
template <typename T>
T* fooHelper() {return new T;} // Simple example here.
};
template <typename T>
T* bar (A* a) {
return a->foo(T{});
}
int main() {
B* b = new B;
Base* list[] = {bar<Object>(b), bar<Thing>(b), bar<Blob>(b)};
for (const Base* x : list) x->show();
}
此解决方案的问题在于,只有T
的类型不多,才可行。但如果有呢?此外,以后引入T
的新类型时会出现维护问题。
有人能想出比这更好的解决方案吗?作为虚拟模板变通方法的已知访问者模式在此处不适用(我不认为),因为模板未出现在参数中。
答案 0 :(得分:1)
...
T* fooHelper() {return new T;}
};
template <typename T>
T* create (A* a) {
return a->foo(T{});
}
A的实例对你返回的T没有影响。我假设也许这应该是一个论点。你好像想要一家工厂。如何使用成员函数:
template < typename T, typename FactoryType,
typename MemFnType, typename ArgType >
T* create(FactoryType* f, MemFnType mfn, ArgType a)
{
return (f->*mfn)(a);
}
完整示例:
#include <iostream>
struct Base { virtual void show() const = 0; };
struct Object : Base { virtual void show() const override {std::cout << "I am an Object.\n";} };
struct Thing : Base { virtual void show() const override {std::cout << "I am a Thing.\n";} };
struct Blob : Base { virtual void show() const override {std::cout << "I am a Blob.\n";} };
struct Args
{
int someArg;
};
struct Factory
{
// normally 'a' would be passed to the Object constructor.
// omitted to save edits.
Object* asObject(const Args& a) { return new Object(); }
Thing* asThing(const Args& a) { return new Thing(); }
Blob* asBlob(const Args& a) { return new Blob(); }
};
template < typename T, typename FactoryType,
typename MemFnType, typename ArgType >
T* create(FactoryType& f, MemFnType mfn, ArgType& a)
{
return (&f->*mfn)(a);
}
int main() {
Args arg;
Factory f;
Base* list[] = {create<Object>(f, &Factory::asObject, arg), create<Thing>(f, &Factory::asThing, arg), create<Blob>(f, &Factory::asBlob, arg)};
for (const Base* x : list) x->show();
}
添加可构造类型只需要添加类型本身和相关的工厂函数。您甚至可以将其概括为完整模板参数列表而不是单个参数类型。