如何强制接口?

时间:2010-11-07 17:13:23

标签: c++

我应该如何确保作为模板类的参数之一所需的类将具有某个接口?我知道一种方法是在Interface类中使用pure virtual,但我想避免它。还有其他办法吗?我想避免任何不标准的事情

    //Example  
    template<class SomePolicy>  
    class My
    {
void fnc()const
{
SomePolicy::mustHaveThisInterface();//<--here I have to have  
// this interface in orded to work

}
    };

6 个答案:

答案 0 :(得分:4)

问题是你的意思是“界面”。如果您只是想要让类包含某些方法,只需使用这些方法即可。如果给模板的类没有它们,如果您尝试使用该类实例化模板,则会出现编译错误。

只有在您尝试使用的所有方法实际存在时才会编译。

答案 1 :(得分:4)

Stroustrup为此撰写了解决方案。查看herehere

答案 2 :(得分:2)

一个简单的解决方案是使用验证需求的虚函数。例如:

class Interface {};

    // Basically a no-op, but has to compile.
template<typename I, typename T>
void require ()
{
    T * t = 0; I * i = t;
}

template<class SomePolicy>
class My
{
    void fnc () const
    {
            // won't compile unless `SomePolicy` inherits `Interface`.
        require<Interface, SomePolicy>();
    }
};

请注意,由于这是一个模板,除非调用My<T>::fnc(),否则不会编译require<I,T>(),这意味着您的验证SomePolicy指令必须放在重要位置(例如构造函数,或者Interface必须继承{{1}}的每个函数的开头。)您放置的检查数量取决于您的偏执程度。

性能注释:由于检查相当于无操作,任何体面的编译器都会对其进行优化,因此在运行时或内存中不会花费任何成本。编译器仍然有义务使其成为可编译的,这意味着它不能在编译时跳过测试。

答案 3 :(得分:2)

根据“界面”的含义,您发布的代码可能已经完成了工作:

//Example  
template<class SomePolicy>  
class My
{
    void fnc() const
    {
        SomePolicy::mustHaveThisInterface();
        // this interface in orded to work
    }
};

如果mustHaveThisInterface()类未定义SomePolicy,则此代码将无法编译。因此,已经保证策略类具有正确的接口。

如果您希望确保SomePolicy派生自定义虚拟mustHaveThisInterface的某个接口类,那么您可以使用TR1中添加的std::is_base_of标头中的type_traits (以前可从Boost获得):

当且仅当std::is_base_of<MyInterface, SomePolicy>::value来自SomePolicy时,

MyInterface才会为真。

答案 4 :(得分:1)

您应该能够使用type_traits和SFINAE来保证SomePolicy继承自接口。

template<typename T> class My {
    typedef typename std::enable_if<
        std::is_base<
            T,
            some_interface
        >::value,
        bool
    >::type __traits__impl; // Won't compile if T does not inherit from interface
};

答案 5 :(得分:1)

Boost有一个名为Concept Check的库,仅用于此用途。它可用于确保模板的任何类型参数具有操作该模板所需的最小功能。它附带了对所有标准库接口的检查,并向您展示了如何为您发明的接口编写自己的接口。