有条件地在c ++中强制执行模板类型

时间:2014-11-28 12:22:13

标签: c++ templates

我有一个类模板,需要能够通过从我拥有的Compare类派生的比较对象来比较两个对象:

template<typename T>
class Container {
public:
    template<typename A, typename B>
    class Compare {
    public:
        virtual bool eq(const A&, const B&) const = 0;
    };

我提供了默认的比较对象,假设类型T具有运算符==

    template<typename A, typename B>
    class Default : public Compare<A,B> {
    public:
        bool eq(const A& a, const B& b) const { return a==b; }
    };
private:
    Compare<T,T>* comparison_object;
    bool uses_default;
    Container() : comparison_object(new Default<T,T>()), uses_default(true) {}
    Container(Compare<T,T>& cmp) : comparison_object(&cmp), uses_default(false) {}
    ~Container() { if(uses_default) delete comparison_object; }
};

但是,当我尝试使用具有operator==重载的自定义类进行编译时(即使我提供了从Compare派生的对象):< / p>

MyObjCmp moc;
Container<MyObj>(&moc);

编译器抱怨操作员不存在:

error: no match for 'operator==' (operand types are 'const MyObj' and 'const MyObj')

这是有道理的,因为即使我不需要它,仍然需要创建Default类。但现在我需要一个解决方法......

有什么想法吗?

2 个答案:

答案 0 :(得分:4)

您可以使用编译时检查没有对象,而不是对空指针进行运行时检查:

Container() : comparison_object(new Default<T,T>), uses_default(true) {}
Container(Compare<T,T>& cmp) : comparison_object(&cmp), uses_default(false) {}

默认构造函数,因此Default只会在需要时进行实例化,因此在使用非Default失败的类型的非默认构造函数时没有错误。

但是要小心处理像这样的原始指针,这是内存泄漏的一个秘诀,更糟糕的是。不要忘记CompareRule of Three的虚拟析构函数,并且要非常小心非默认比较器不会意外销毁。更好的是,使用智能指针来处理所有这些。

答案 1 :(得分:0)

template<typename T1, typename T2 >
class Container {
public:
    template<typename T3, typename T4 >
    class Compare {
    public:
        virtual bool eq(const T1&, const T2&) const = 0;
    };


    class Default : public Compare {
    public:
        bool eq(const T1& a, const T2& b) const { return a==b; }
    };

private:
    Compare<T1,T2>* comparison_object;
    bool uses_default;
    Container(Compare<T1,T2>* cmp) : comparison_object(cmp), uses_default(false) {
        if (!cmp) {
            comparison_object = new Default<T,T>();
            uses_default = true;
        }
    }
    ~Container() { if(uses_default) delete comparison_object; }
};