0

我有一个带有模板函数的类:

富.h:

class Foo {
public:
    int some_function();
    bool some_other_function(int a, const Bar& b) const;

    template<typename T>
    int some_template_function(const T& arg);
};

template<typename T>
int Foo::some_template_function(const T& arg){
   /*...generic implementation...*/
}

现在我已经到了希望能够通过代理类访问 Foo 的地步,就像在代理设计模式中一样。


直观地说,我想重构如下(以下代码不正确,但它表达了我的“理想化”API):

FooInterface.h:

class FooInterface {
public:
    virtual int some_function()=0;
    virtual bool some_other_function(int a, const Bar& b) const=0;

    template<typename T>
    virtual int some_template_function(const T& arg)=0;
};

FooImpl.h:

#include "FooInterface.h"

/** Implementation of the original Foo class **/
class FooImpl : public FooInterface {
public:
    int some_function();
    bool some_other_function(int a, const Bar& b) const;

    template<typename T>
    int some_template_function(const T& arg);
};

template<typename T>
int FooImpl::some_template_function(const T& arg){
   /*...generic implementation...*/
}

FooProxy.h:

#include "FooInterface.h"

class FooProxy : public FooInterface{
protected:
    FooInterface* m_ptrImpl; // initialized somewhere with a FooImpl*; unimportant in the context of this question
public:
    int some_function()
        { return m_ptrImpl->some_function(); }
    bool some_other_function(int a, const Bar& b) const
        { return m_ptrImpl->some_other_function(a,b); }

    template<typename T>
    int some_template_function(const T& arg)
        { return m_ptrImpl->some_template_function(arg); }
};

但是这段代码惨遭失败。

首先,FooImpl不能编译,因为类模板函数不能是虚拟的。

更重要的是,即使我玩弄 的定义some_template_function,即使我将它重新定位到一个具体的类或其他一些陪审团操纵,它仍然会对在首先,因为模板代码需要在标题中定义并包含在内。这将强制FooProxy.h包含FooImpl.h,并且FooImpl.h需要实现所需的所有实现细节和文件包含some_template_function。因此,如果我使用代理模式来掩盖实现细节,使自己远离具体实现,并避免不必要的文件包含,那么我就不走运了。

有没有办法将代理模式或其一些变体应用于具有模板函数的类?或者这在 C++ 中是不可能的吗?


背景:目前,我正在尝试为一组具有预先存在的内置日志记录机制的类提供代理访问。我为该日志提供的唯一 API 使用可变参数模板,因此无法预测将使用的参数组合。我希望实现和使用代理的客户端之间的分离尽可能干净,我需要尽量减少从客户端到实现的依赖关系,但我确实需要它们写入同一个日志。

但是,我对这个问题感兴趣,而不是我的直接问题。让我感到困惑的是,模板在主要设计模式中戳出这样一个漏洞,而且我还没有发现这个问题在任何地方都得到了解决。

4

1 回答 1

2

具有模板化接口的类的包装器/代理将始终要求模板类的定义在调用包装器的代码的头文件中可见。这是因为为模板化接口生成的代码取决于调用它的参数的类型。

如果您坚持使用现有的模板化实现FooImpl,那么正如@mars 在评论中所写,您唯一的选择是:

template <class Implementation>
class FooProxy
{
    Implementation * m_ptrImpl;
    //...
};

如果您可以更改现有的实现,理想的解决方案是重构模板化方法并将它们分成两层;一层依赖于参数类型,第二层不依赖于参数类型。现有方法中依赖于参数类型的代码在所有实现中应该是相同的,因此可以将该层移到抽象接口类的方法中。不依赖于参数类型的剩余代码可以留在实现类的非模板化方法中,这意味着实现细节可以隐藏在 .cpp 文件中。

下面是一个例子,基于支持写入任意类型的日志场景:

LogInterface.h

class LogInterface {
public:
    template<typename T>
    void write(const T& arg)
    {
        // converts from 'T' to array of characters.
        // calls non-template 'write' as many times as necessary.
    }

    virtual void write(const char* p, std::size_t n)=0;
};

LogImpl.h

#include "LogInterface.h"

/** Implementation of the original Log class **/
class LogImpl : public LogInterface {
public:
    void write(const char* p, std::size_t n);
};

LogProxy.h

#include "LogInterface.h"

class LogProxy : public LogInterface{
protected:
    LogInterface* m_ptrImpl; // initialized somewhere with a LogImpl*
public:
    void write(const char* p, std::size_t n)
        { m_ptrImpl->write(p, n); }
};
于 2013-08-05T11:59:56.967 回答