检查模板类是否存在功能

时间:2014-11-17 23:02:49

标签: c++ templates

我想检查一个提供的模板类,以确定在编译时存在一些方法。编写示例代码:

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上已经发现了这个问题,指出了

  

http://www.gotw.ca/gotw/071.htm

但我不明白这种无辜的单行解决方案:

// in Validation method:
T* (T::*test)() const = T::Clone; // checks for existence of T* T::Clone() const

感谢任何帮助。

(如果没有访问默认的ctor是不可能的,我可能会放弃该要求。)

1 个答案:

答案 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函数返回truefalse(就像您现在尝试的那样),这意味着运行时决定。所以你必须使用这种技巧,如果函数存在,那么程序将编译,如果没有,你将得到一个编译时错误。

因此,在您的情况下,为了测试double AudioSystem::hasFeature(int, double)的存在,您需要声明

double (AudioSystem::*test)(int, double) = AudioSystem::hasFeature;