检查模板类是否存在函数

Check template class for existence of function

本文关键字:存在 函数 是否 检查      更新时间:2023-10-16

我想在编译时检查提供的模板类是否存在某些方法。编造的示例代码:

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对象,所以我不能只对方法进行测试调用。另外:我不能假设音频系统的默认 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 的情况下无法实现,我也许可以放弃该要求。

T* (T::*test)() const = T::Clone;

声明test为指向T的常量成员函数的指针,后者不带任何参数并返回指向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
}

现在尝试从 Foo::Clone() 的签名中删除const,或使其返回 int ,您将获得编译时错误,因为 Check<T> 中声明的指针不再与正确类型的函数兼容。希望这是有道理的。

请注意,这种验证是在编译时完成的,因此您不能使用返回truefalsebool函数(就像您现在尝试执行的那样),因为这意味着运行时决策。所以你必须使用这种技巧,如果函数存在,那么程序将编译,如果没有,你会得到一个编译时错误。

因此,在您的情况下,例如要测试是否存在double AudioSystem::hasFeature(int, double),您需要声明

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