需要虚函数的模板 return 类型

Template return type of a function that needs to be virtual

因为以下是非法的:

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.
}

并且模板只出现在 return 类型中,我想到了一个(天真的?)使用重载的解决方法:

#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 的新类型时会出现维护问题。

有人能想出比这更好的解决方案吗?作为虚拟模板解决方法的已知访问者模式不适用于此处(我不认为),因为该模板未出现在参数中。

...
    T* fooHelper() {return new T;}
};

template <typename T>
T* create (A* a) {
    return a->foo(T{});
}

A​​实例对T你没有影响return。我假设这应该是一个论点。看起来你也想要一个工厂。如何使用成员函数:

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();
}

添加可构造类型只需要添加类型本身和相关的工厂函数。您甚至可以将其概括为完整的模板参数列表,而不是单个参数类型。