【问题标题】:Conditionally enforce template types in c++在 C++ 中有条件地强制执行模板类型
【发布时间】:2014-11-28 12:22:12
【问题描述】:

我有一个类模板,它需要能够通过比较从我拥有的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 派生的对象)的自定义类来编译它时:

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

编译器报错操作符不存在:

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

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

有什么想法吗?

【问题讨论】:

  • Compare&lt;T,T&gt;* comparison_object; 导致内存泄漏。请使用std::unique_ptrstd::shared_ptr,而不是直接使用new/delete
  • 我的析构函数会处理它...我有一个“default_created”布尔标志和条件删除,别担心 :)
  • @Niall,我会编辑它...我认为没关系
  • @remyabel:它被标记为 C++,现在这意味着 C++11(或者可能是 14,我不确定这是否是正式的标准)。
  • @remyabel:我想是的,尽管最好的答案会在他们使用新功能时提及,并为那些过去的人建议解决方法。不过,这只是我的看法。

标签: c++ templates


【解决方案1】:

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

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 的虚拟析构函数,并且要非常小心,非默认比较器不会被意外破坏。更好的是,使用智能指针为您处理所有这些。

【讨论】:

  • 但我仍然需要在第二个构造函数中检查 NULL,如果需要创建一个 Default&lt;T,T&gt;... 回到第一格
  • @Dori:确实,我忘了提到您应该使用引用而不是指针,以确保它不能为空。如果您想要默认比较器,请使用默认构造函数。
  • 不。当编译器读取这一行时,它会实例化Default&lt;T, T&gt;,不是吗?
  • @ikh:我不这么认为,我(几乎)确定只有在实例化构造函数时才应该这样做。不过我最好检查一下。
  • @MikeSeymour 嗯,It seems that you're right,但我很困惑 - 我会发布答案 >o
【解决方案2】:
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; }
};

【讨论】:

    猜你喜欢
    • 2013-07-14
    • 1970-01-01
    • 2021-10-01
    • 1970-01-01
    • 2021-12-08
    • 2012-01-09
    • 2015-08-01
    • 2010-09-27
    • 1970-01-01
    相关资源
    最近更新 更多