2016-02-09 3 views
1

C++ 11 позволяет проверить, достаточно сжато, для существования члена: Is it possible to write a template to check for a function's existence?Проверка существования глобальной (/ пространство имен) функции/объекта декларации

Можно ли проверить наличие объявления глобальной функции (с именами или без них)?

Детали: В моем конкретном случае, я хотел бы проверить, если моя реализация stdio.h (#include d) определяет, например, fprintf_unlocked (со стандартной подписи) и использовать его, если он делает, в противном случае по умолчанию fprintf.

+0

Если имя существует, мы можем проверить его подпись/или если он может принимать некоторые параметры. – Jarod42

+0

@ Jarod42 Я хотел бы проверить, объявлен ли 'int :: fprintf_unlocked (FILE *, const char *, ...)'. Как я могу это сделать? – PSkocik

+0

У меня возникли трудности с поиском документов для 'fprintf_unlocked'. это то же самое, что и 'fprintf', кроме без автоматической защиты потоков на gnu libc? – jaggedSpire

ответ

3

способ проверить существование функции, Вы можете создать следующие черты:

#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature)    \ 
    template <typename U>             \ 
    class traitsName              \ 
    {                  \ 
    private:                \ 
     template<typename T, T> struct helper;        \ 
     template<typename T>            \ 
     static std::uint8_t check(helper<signature, &funcName>*);   \ 
     template<typename T> static std::uint16_t check(...);    \ 
    public:                 \ 
     static                \ 
     constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \ 
    } 

DEFINE_HAS_SIGNATURE(has_foo, foo, T*); 
DEFINE_HAS_SIGNATURE(has_bar, bar, T*); 

А затем проверить его

has_foo<void(int)>::value 

Demo

+1

Macro, barf;) И '& funcName' не работает для перегруженных имен. –

+0

Ох, на самом деле это действительно работает, извините! Шаблон «helper» достаточно, чтобы принудить указатель функции к правильному типу. –

+1

@Jonathan Wakely Я попробовал, и он действительно работал с перегруженными именами. Я предполагаю, что он находит правильный, который создает «helper», если такая функция существует с 'funcName'. К сожалению, он полностью не скомпилируется, если есть, если 'funcName' не объявлен вообще, но не проблема объявлять (а не определять) поддельную. – PSkocik

0

Я сделал гибридную черты генератора макрос, который проверяет либо членов, либо свободные постоянные функции.

Это создает классы шаблонов шаблонов, которые смотрят, работает ли поставленная пользователем подпись (первый шаблон arg) с именем, встроенным в класс признаков.

Он ищет свободностоящие имена, если второй параметр шаблона не задан (Trait<Sig>::value) или для члена второго аргумента шаблона, если шаблон шаблонов создается с двумя аргументами (Trait<Sig,ClassToSearch>::value).

Он может выполнять поиск только бесплатных функций, которые были объявлены до того, как был определен класс шаблонов.

#define DEF_HAS_SIG(TraitsName, funcName) \ 
std::nullptr_t funcName(...); \ 
template<typename Sig, typename Type=void> class TraitsName { \ 
    typedef char yes[1];          \ 
    typedef char no [2];          \ 
    template <typename U, U> struct TypeCheck;     \ 
    template <typename _1, typename _2 > static no &chk(...); \ 
    template <typename _1, typename _2> static     \ 
    typename std::enable_if< std::is_same<void,_2>::value, yes&>::type chk(TypeCheck<_1, &funcName > *); \ 
    template <typename _1, typename _2> static yes& chk(TypeCheck<_1, &_2::funcName > *);     \ 
public: static bool const value = sizeof(chk<Sig,Type>(0)) == sizeof(yes);        \ 
}; 
+0

(Извинения за форматирование.Я не пишу прямо в C++, а скорее сгенерировал его с моего мини-языка, который, среди прочего, сокращает все ключевые слова, что означает, что оригинальные взгляды менее неуклюжи.) – PSkocik

Смежные вопросы