Проверка, существует ли функция с данной сигнатурой в c ++ - PullRequest
2 голосов
/ 17 января 2011

Поэтому я искал способы проверить, существует ли функция с определенным аргументом.У меня есть шаблонный метод, который опирается на внешнюю функцию (внешнюю от класса) для выполнения работы:

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

В нескольких точках проекта у меня есть макросы, которые определяют extended_solid_loader для разных типов, но теперь яхотите иметь возможность использовать функцию по умолчанию, если extended_solid_loader не был определен для этого конкретного типа класса.

Я сталкивался с этим: Можно ли написать шаблон для проверки существования функции? но это выглядит немного иначе, поскольку я проверяю не метод, а определение функции с определенным типом аргумента.

Возможно ли это сейчас?

Ответы [ 2 ]

5 голосов
/ 17 января 2011

Вы можете просто предоставить шаблон функции для extended_solid_loader, обеспечивающей реализацию по умолчанию, а пользователи, которые хотят использовать что-то отличное от реализации по умолчанию, просто специализируют это.

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
}
2 голосов
/ 17 января 2011

На самом деле вам не нужно делать ничего особенного.Просто убедитесь, что есть версия этой функции, доступная для шаблона, и пусть ADL сделает грязную работу.Посмотрите на этот пример:

#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();
}

Работает и без пространства имен (не-шаблоны имеют предпочтение).Я просто использовал это, чтобы показать, что ADL поднимет его, когда вы это сделаете.


Ваш оригинальный вопрос был интересным.Нашел способ сделать это в 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();
}
...