简体   繁体   中英

Checking if a function with a given signature exists in c++

So I was looking for ways to check whether a function with a particular argument exists. I have a templated method which relies on an external function (external from the class) to do the job:

  template <class Moo>
  void exportDataTo(Moo& ret){
     extended_solid_loader(ret, *this);
  }

At multiple points in the project I have macros which define extended_solid_loader for different types, but now I want to be able to use a default function if extended_solid_loader hasn't been defined for that particular class type.

I came across this: Is it possible to write a template to check for a function's existence? but it seems a little different, in that I'm not checking for a method, but rather a definition of a function with a particular argument type.

Is this possible right now?

You can just provide a function template for extended_solid_loader providing a default implementation, and users who want to use something other than the default implementation just specialize that.

template<class T>
void extended_solid_loader(T & ret, SomeClass & obj) {
    // default implementation here
}

template<>
void extended_solid_loader<MooClass>(MooClass & ret, SomeClass & obj) {
    // special implementation for MooClass here
}

You don't actually have to do anything particularly special. Just make sure there's a version of that function available to the template and let ADL do the dirty work. Check out this example:

#include <iostream>

namespace bob {

  struct X {};

  void f(X const&) { std::cout << "bob::f\n"; }
}

namespace ed {

  template < typename T >
  void f(T const&) { std::cout << "ed::f\n"; }

  template < typename T >
  struct test
  {
    void doit() // not called f and no other member so named.
    { f(T()); }
  };

}

int main()
{
  ed::test<int> test1;
  ed::test<bob::X> test2;

  test1.doit();
  test2.doit();

  std::cin.get();
}

Works without the namespace stuff too (non-templates have preference). I just used that to show that ADL will pick it up when you do.


Your original question was interesting. Found a way to do it in C++0x:

template < typename T >
struct fun_exists
{
  typedef char (&yes) [1];
  typedef char (&no)  [2];

  template < typename U >
  static yes check(decltype(f(U()))*);

  template < typename U >
  static no check(...);

  enum { value = sizeof(check<T>(0)) == sizeof(yes) };
};

void f(double const&) {}

struct test {};

#include <iostream>
int main()
{
  std::cout << fun_exists<double>::value << std::endl;
  std::cout << fun_exists<test>::value << std::endl;

  std::cin.get();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM