我想检查一个提供的模板类,以确定在编译时存在一些方法。编写示例代码:
template <class AudioSystem>
class Car {
public:
Car() {/*nothing related to AudioSystem*/}
void getsCalledLater(AudioSystem* a) {/*...*/}
void Verify() {
// check if class AudioSystem has function double hasFeature(int, double)
// check if class AudioSystem has function double getCreationDate()
}
~Car() {
Verify();
}
};
当构造函数被调用时,我没有AudioSystem
对象,所以我不能只对这些方法进行测试调用。另外:我不能假设AudioSystem的默认ctor可用。
我在SO上已经发现了这个问题,指出了
但我不明白这种无辜的单行解决方案:
// in Validation method:
T* (T::*test)() const = T::Clone; // checks for existence of T* T::Clone() const
感谢任何帮助。
(如果没有访问默认的ctor是不可能的,我可能会放弃该要求。)
答案 0 :(得分:1)
该行
T* (T::*test)() const = T::Clone;
将test
声明为指向T
的const-member-function的指针,后者不带参数并返回指向T
的指针。然后它初始化为指向T::Clone
成员函数。现在,如果T::Clone
的签名与(void)->T*
不同或不存在,那么您将收到错误。
非常聪明。
让我们来看看这个例子:
template<typename T>
class Check // checks for the existence of `T* T::Clone() const`
{
public:
~Check()
{
T* (T::*test)() const = &T::Clone;
// test; // don't think you need this line
}
};
class Foo
{
public:
Foo* Clone() const{}; // try changing the signature, remove `const` for example
};
int main()
{
Check<Foo> testFoo; // ok
}
现在尝试从const
的签名中删除Foo::Clone()
,或者让它返回int
,并且您将获得编译时错误,因为指针在Check<T>
与正确的函数类型不兼容。希望这是有道理的。
请注意,此类验证是在编译时完成的,因此您无法使用bool
函数返回true
或false
(就像您现在尝试的那样),这意味着运行时决定。所以你必须使用这种技巧,如果函数存在,那么程序将编译,如果没有,你将得到一个编译时错误。
因此,在您的情况下,为了测试double AudioSystem::hasFeature(int, double)
的存在,您需要声明
double (AudioSystem::*test)(int, double) = AudioSystem::hasFeature;