我应该如何确保作为模板类的参数之一所需的类将具有某个接口?我知道一种方法是在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
}
};
答案 0 :(得分:4)
问题是你的意思是“界面”。如果您只是想要让类包含某些方法,只需使用这些方法即可。如果给模板的类没有它们,如果您尝试使用该类实例化模板,则会出现编译错误。
只有在您尝试使用的所有方法实际存在时才会编译。
答案 1 :(得分:4)
答案 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的库,仅用于此用途。它可用于确保模板的任何类型参数具有操作该模板所需的最小功能。它附带了对所有标准库接口的检查,并向您展示了如何为您发明的接口编写自己的接口。