2016-05-05 2 views
1

Прочитав вопрос с Is it possible to write a C++ template to check for a function's existence? и протестировав несколько ответов, я нахожу, что он работает только при обнаружении функций, которые не принимают никаких параметров, EG void HelloWord(). Поиск по ответам просто дает решения для беспараметричных функций или сложных для глаз решений, которые я не могу сделать ни головы, ни хвост.Проверка наличия в классе функции с параметрами

Вот мой код макроса шаблон для построения детекторов:

#define MEMBERFUNCTIONTODETECT(CONTAINS_NAME,MEMBERFUNCTION) \ 
template <typename TemplateItem>\ 
class CONTAINS_NAME\ 
{\ 
    typedef char Yes;\ 
    typedef char No[2];\ 
\ 
    template <typename TemplateClass> static Yes &Test(decltype(&TemplateClass::MEMBERFUNCTION));\ 
    template <typename TemplateClass> static No &Test(...);\ 
\ 
public:\ 
    enum { Value = sizeof(Test<TemplateItem>(0)) == sizeof(char) };\ 
}; 

Как изменить код выше, чтобы обнаружить функцию-член в классе, который содержит параметры, EG недействительными SetPosition (с плавающей точкой, с плавающей точкой) ?

Я готов принять решения, которые являются общими перезаписываниями, но если какие-либо решения сложнее, чем выше, попробуйте объяснить, что происходит на максимально возможной глубине, чтобы я (и, предположительно, другие) мог понять, как оно работает. Обращайтесь со мной так, как будто я понятия не имею, что значит что-то из того, что вы написали.

+0

вы уверены, что вы хотите, чтобы проверить, есть ли функция конкретной подписи, как 'ничтожной SetPosition (поплавок, поплавок)', или есть ли функция 'SetPosition' Tak может принимать два значения неявно конвертируется в плавать? –

+0

Конкретная подпись или неявно конвертируемая версия, любой из них будет в порядке для моих нужд. Я, вероятно, лучше работаю с конкретной подписью, так как могу аргументы макроса шаблона, хотя я открыт для любых решений, которые решают эту проблему. – c1646091

+0

[Здесь] (http://coliru.stacked-crooked.com/a/72426d6be71e55a5) решение, использующее идиому обнаружения. –

ответ

2

Так как вы хотите, чтобы проверить, как, есть ли функция член конкретной подписи, а также, является ли данная функция вызываемая с некоторыми типами аргументов, вы могли бы использовать detection idiom для этого:

#include <type_traits> 
#include <utility> 

template <typename...> 
using void_t = void; 

template <typename AlwaysVoid, template <typename...> class Operation, typename... Args> 
struct detect_impl : std::false_type {}; 

template <template <typename...> class Operation, typename... Args> 
struct detect_impl<void_t<Operation<Args...>>, Operation, Args...> : std::true_type {}; 

template <template <typename...> class Operation, typename... Args> 
using detect = detect_impl<void_t<>, Operation, Args...>; 

Теперь вам просто нужно добавить некоторые пользовательские детекторы:

// Check specific signature 
template <typename T, typename Sig> 
using has_SetPosition = decltype(static_cast<Sig>(&T::SetPosition)); 

// Check if the function can be called with Args... 
template <typename T, typename... Args> 
using can_call_SetPosition = decltype(std::declval<T>().SetPosition(std::declval<Args>()...)); 

Тесты:

struct A 
{ 
    void SetPosition(float, float) {} 
}; 

struct B 
{ 
    void SetPosition(int, int) {} 
}; 

struct C 
{ 
}; 

int main() 
{ 
    static_assert(detect<has_SetPosition, A, void(A::*)(float, float)>{}, "!"); 
    static_assert(!detect<has_SetPosition, B, void(B::*)(float, float)>{}, "!"); 
    static_assert(!detect<has_SetPosition, C, void(C::*)(float, float)>{}, "!"); 

    static_assert(detect<can_call_SetPosition, A&, float, float>{}, "!"); 
    static_assert(detect<can_call_SetPosition, B&, float, float>{}, "!"); 
    static_assert(!detect<can_call_SetPosition, C&, float, float>{}, "!"); 
} 

Обратите внимание на разницу с классом B, в то время как первый признак отклоняет этот класс, второй оценивается как true.

DEMO

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

  • Нет связанных вопросов^_^