c++ - 如何将基于通用迭代器的算法与基于实现的算法结合起来?

标签 c++ templates

我正在使用策略模式和抽象工厂模式在运行时在计算器类中生成不同的算法。

计算将取决于所涉及类型之间的关系。这就是为什么我将“*Algorithm::calculate”作为成员函数模板,就关系而言是通用的。

但是,我已经有了一个在现有代码中完全基于实现的算法,它既不是泛型的也不是基于迭代器的,我想将它添加到算法层次结构中,以便我可以使用 AbstractFactory 生成它以及看看它是如何表现的。

基于实现的算法使用参与计算的类型的成员函数来完成计算。在此示例中,它将使用 RelationshipWithA::target_type 成员函数来访问 Type& 的数据,以及“A”成员函数来访问 RelationshipWithA::a_ 的数据。

这是我到目前为止的想法(这只是一个模型,没有抽象工厂和计算器类):

#include <iostream>

class Result{}; 

class A {};  

class B {
    public: 
        void specific() const 
        { 
            std::cout << "B::specific()" << std::endl;
        };
};

class C : public B {};

class D {};

template<class Type>
class RelationshipWithA
{
    const A& a_; 

    const Type& t_;

    public: 
        typedef Type target_type; 

        RelationshipWithA (const A& a, const Type& t)
            :
                a_(a), 
                t_(t)

        {
            std::cout << "RelationshipWithA::ctor" << std::endl;
        }; 

        const A& a() const 
        {
            return a_; 
        }

        const Type& type() const
        {
            return t_;
        }
};

class DefaultAlgorithm 
{
    public:
        template <class Relationship>
        void calculate (Result& res, const Relationship& r)
        {
            std::cout << "DefaultAlgorithm::calculate" << std::endl;
            const A& a = r.a(); 
            const typename Relationship::target_type& t = r.type(); 
            // Default iterator based calculation on a, target_type and r
        };
};

class AlternativeAlgorithm 
: 
    public DefaultAlgorithm 
{
    public:
        template <class Relationship>
        void calculate (Result& res, const Relationship& r)
        {
            std::cout << "AlternativeAlgorithm::calculate" << std::endl;
            // Optimized iterator based calculation on a, target_type and r
        }
};

class ImplementationBasedAlgorithm 
:
    public DefaultAlgorithm 
{
    public:
        // No specialization: Relationships store
        // a const reference to any class that inherits from B
        template <class Relationship>
        void calculate (Result& res, const Relationship& r)
        {
            // Use B implementation and the Relationship With  A to compute the result
            std::cout << "ImplementationBasedAlgorithm::calculate" << std::endl;
            const A& a = r.a(); 
            const B& b = r.type();
            b.specific();
            // Implementation based on B implementation
        }
};

int main(int argc, const char *argv[])
{
    Result res; 

    A a; 
    C c; 

    RelationshipWithA<C> relationshipAC (a, c);

    DefaultAlgorithm defaultAlg; 
    AlternativeAlgorithm alternativeAlg;
    ImplementationBasedAlgorithm implementationAlg;

    defaultAlg.calculate(res, relationshipAC);
    alternativeAlg.calculate(res, relationshipAC);
    implementationAlg.calculate(res,relationshipAC);

    D d; 
    RelationshipWithA<D> relationshipAD (a, d);

    defaultAlg.calculate(res, relationshipAD);
    alternativeAlg.calculate(res, relationshipAD);
    // This fails, as expected
    //implementationAlg.calculate(res,relationshipAD);

    return 0;
}

我喜欢这种设计,因为算法不是通用类,这使得通用抽象工厂很容易在运行时生成它们。

然而,在 Effective C++ 中有一个条款 36 说:“永远不要重新定义一个继承的非虚函数”。我的意思是,非虚函数是实现不变的,它们通常不应该被覆盖,但是:

  1. C++ 中没有可用的虚成员函数模板。
  2. 如果我使算法类在 RelationshipWithA 上通用并且“*Algorithm::calculate”成为一个虚拟成员函数,工厂需要了解 Realtionship 才能生成算法,并且代码会变得非常臭(至少对我来说是这样) ).

即使我覆盖了继承的非虚函数(函数模板),这是否是解决问题的合适方法?

对于客户来说,行为没有任何区别:结果就在那里,唯一的区别在于它的计算方式。这意味着仍然支持 Is-A 关系:“*Algorithm::calculate”对于客户端来说仍然是实现不变的。

最佳答案

这不是一个真正的Is-A关系...

具体的实现并不是真正的默认算法...它们是具体的算法...

您可以使用工厂创建一个空的 BaseAlgorithm 类。但是在使用模板函数之前,无论如何你都需要将它转换为正确的类型。无论如何,这有点胜过工厂模式,因为您没有使用接口(interface)。

在您的情况下,如果工厂创建派生类之一但返回基类,如果您使用该变量,它将调用基类方法:

DefaultAlgorithm algo = Factory.CreateImplementationBasedAlgorithm();
RelationshipWithA<D> relationshipAD (a, d);
algo.calculate(res, relationshipAD); //won't fail because the base class methods are used (because it isn't virtual)

要解决这个问题,您可以创建一个 Relationship 基类,并将 calculate() 方法设置为虚拟方法。
calculate() 方法将获取,然后您可以将 Relationship static_cast 到某个 base_relationship 接口(interface),该接口(interface)具有该算法所需的接口(interface),因此您可以因没有正确的 而导致编译失败a()type() 方法。

关于c++ - 如何将基于通用迭代器的算法与基于实现的算法结合起来?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15174815/

相关文章:

c++ - 通过从每个位置的特定位置词池中选择词来高效生成所有序列

c++ - 仅使用前 3 位小数计算,如何?? (c++)

c++ - CUDA: "missing return statement at end of non-void function"in constexpr if 函数

c++ - 我可以通过重新播种结合 random_device 和 mt19937 生成加密安全随机数据吗?

c++ - 如何检查可变参数模板中的非原始类型?

c++ - 将 UTC 中的 QDateTime 转换为本地系统时间

C++ 调用显式模板构造函数

c++ - 在现代 C++ 中使用模板替换函数指针数组

templates - 创建针对特定索引ES 6.x的Elasticsearch模板

templates - 内省(introspection)模板参数(尤其是模板别名参数)