Сообщение Есть ли метод у класса - HasMethod - старая тема от 08.11.2019 22:11
Изменено 09.11.2019 11:25 Molchalnik
Есть ли метод у класса - HasMetod - старая тема
Искал на нашем форуме SFINAE фишку по определению наличия класса в методе — нашёл только очень старую тему, написанную по старому стандарту, и которую крайне трудно адаптировать, потому что проще для каждого нового метода написать с нуля.
Решил обновить вопрос. Не претендую на новизну и оригинальность, наверняка кто-то где-то уже сделал так или почти так. Но на нашем форуме не нашёл, поэтому счёл уместным поднять вопрос снова.
начнём с простого — зададим конкретный метод
Но если надо будет сделать то же для другого метода, всё придётся переписывать. А кода много. Неудобно. Что делать? Нетрушные методы — макросы — помогут нам
Теперь, задав один макрос, мы получаем структурку с заданным 1м параметром именем, позволяющую нам определить наличие у любого класса метода с заданным 2м параметром именем
Решил обновить вопрос. Не претендую на новизну и оригинальность, наверняка кто-то где-то уже сделал так или почти так. Но на нашем форуме не нашёл, поэтому счёл уместным поднять вопрос снова.
начнём с простого — зададим конкретный метод
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
struct A {
//const char * AaBbCcDd(int i) { return "aa"; }
void AaBbCcDd() {}
};
struct B {};
template <typename T> struct HasMethod {
private:
struct HasMethodHelperFalse {
static constexpr const bool value = 0;
};
template <class T2, decltype(&T2::AaBbCcDd) U = &T2::AaBbCcDd > struct HasMethodHelperTrue {
static constexpr const bool value = 1;
};
HasMethodHelperFalse static constexpr detect(...) { return HasMethodHelperFalse(); }
template <typename T2> HasMethodHelperTrue<T2> static constexpr detect( T2 * ) { return HasMethodHelperTrue<T2>(); }
public:
static constexpr const bool value = decltype( detect( static_cast<T*>( nullptr ) ) ):: value;
};
int main() {
printf("\n%u %u %u", HasMethod<A>::value, HasMethod<B>::value, HasMethod<int>::value );
return 0;
}
Но если надо будет сделать то же для другого метода, всё придётся переписывать. А кода много. Неудобно. Что делать? Нетрушные методы — макросы — помогут нам
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
struct A {
const char * SomeFun(int i) { return "aa"; }
void AaBbCcDd() {}
};
struct B {};
/// @brief создаёт структурку ClassName с помощью которого можно определить наличие метода FunName в заданном классе (класс задаётся как параметр шаблона)
/// @details пример:
/// HAS_METHOD_DEFINTION( HasPrintMethod, Print )
/// struct S { void Print() {} };
/// void main () {
/// bool exist = HasPrintMethod<S>::value;
/// }
/// @warning не работает, если в методе есть 2 перегрузки метода, наличие которого мы проверяем
#define HAS_METHOD_DEFINITION( ClassName, FunName ) template <typename T> struct ClassName { private: struct HasMethodHelperFalse { static constexpr const bool value = 0; }; template <class T2, decltype(&T2::FunName) U = &T2:: FunName > struct HasMethodHelperTrue { static constexpr const bool value = 1; }; HasMethodHelperFalse static constexpr detect(...) { return HasMethodHelperFalse(); } template <typename T2> HasMethodHelperTrue<T2> static constexpr detect( T2 * ) { return HasMethodHelperTrue<T2>(); } public: static constexpr const bool value = decltype( detect( static_cast<T*>( nullptr ) ) ):: value;};
HAS_METHOD_DEFINITION( HasMethod, AaBbCcDd )
HAS_METHOD_DEFINITION( HasMethod2, SomeFun )
int main() {
printf("\n%u %u %u", HasMethod <A>::value, HasMethod <B>::value, HasMethod <int>::value );
printf("\n%u %u %u", HasMethod2<A>::value, HasMethod2<B>::value, HasMethod2<int>::value );
return 0;
}
Теперь, задав один макрос, мы получаем структурку с заданным 1м параметром именем, позволяющую нам определить наличие у любого класса метода с заданным 2м параметром именем
Есть ли метод у класса - HasMethod - старая тема
Искал на нашем форуме SFINAE фишку по определению наличия класса в методе — нашёл только очень старую тему, написанную по старому стандарту, и которую крайне трудно адаптировать, потому что проще для каждого нового метода написать с нуля.
Решил обновить вопрос. Не претендую на новизну и оригинальность, наверняка кто-то где-то уже сделал так или почти так. Но на нашем форуме не нашёл, поэтому счёл уместным поднять вопрос снова.
начнём с простого — зададим конкретный метод
Но если надо будет сделать то же для другого метода, всё придётся переписывать. А кода много. Неудобно. Что делать? Нетрушные методы — макросы — помогут нам
Теперь, задав один макрос, мы получаем структурку с заданным 1м параметром именем, позволяющую нам определить наличие у любого класса метода с заданным 2м параметром именем
Решил обновить вопрос. Не претендую на новизну и оригинальность, наверняка кто-то где-то уже сделал так или почти так. Но на нашем форуме не нашёл, поэтому счёл уместным поднять вопрос снова.
начнём с простого — зададим конкретный метод
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
struct A {
//const char * AaBbCcDd(int i) { return "aa"; }
void AaBbCcDd() {}
};
struct B {};
template <typename T> struct HasMethod {
private:
struct HasMethodHelperFalse {
static constexpr const bool value = 0;
};
template <class T2, decltype(&T2::AaBbCcDd) U = &T2::AaBbCcDd > struct HasMethodHelperTrue {
static constexpr const bool value = 1;
};
HasMethodHelperFalse static constexpr detect(...) { return HasMethodHelperFalse(); }
template <typename T2> HasMethodHelperTrue<T2> static constexpr detect( T2 * ) { return HasMethodHelperTrue<T2>(); }
public:
static constexpr const bool value = decltype( detect( static_cast<T*>( nullptr ) ) ):: value;
};
int main() {
printf("\n%u %u %u", HasMethod<A>::value, HasMethod<B>::value, HasMethod<int>::value );
return 0;
}
Но если надо будет сделать то же для другого метода, всё придётся переписывать. А кода много. Неудобно. Что делать? Нетрушные методы — макросы — помогут нам
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
struct A {
const char * SomeFun(int i) { return "aa"; }
void AaBbCcDd() {}
};
struct B {};
/// @brief создаёт структурку ClassName с помощью которого можно определить наличие метода FunName в заданном классе (класс задаётся как параметр шаблона)
/// @details пример:
/// HAS_METHOD_DEFINTION( HasPrintMethod, Print )
/// struct S { void Print() {} };
/// void main () {
/// bool exist = HasPrintMethod<S>::value;
/// }
/// @warning не работает, если в методе есть 2 перегрузки метода, наличие которого мы проверяем
#define HAS_METHOD_DEFINITION( ClassName, FunName ) template <typename T> struct ClassName { private: struct HasMethodHelperFalse { static constexpr const bool value = 0; }; template <class T2, decltype(&T2::FunName) U = &T2:: FunName > struct HasMethodHelperTrue { static constexpr const bool value = 1; }; HasMethodHelperFalse static constexpr detect(...) { return HasMethodHelperFalse(); } template <typename T2> HasMethodHelperTrue<T2> static constexpr detect( T2 * ) { return HasMethodHelperTrue<T2>(); } public: static constexpr const bool value = decltype( detect( static_cast<T*>( nullptr ) ) ):: value;};
HAS_METHOD_DEFINITION( HasMethod, AaBbCcDd )
HAS_METHOD_DEFINITION( HasMethod2, SomeFun )
int main() {
printf("\n%u %u %u", HasMethod <A>::value, HasMethod <B>::value, HasMethod <int>::value );
printf("\n%u %u %u", HasMethod2<A>::value, HasMethod2<B>::value, HasMethod2<int>::value );
return 0;
}
Теперь, задав один макрос, мы получаем структурку с заданным 1м параметром именем, позволяющую нам определить наличие у любого класса метода с заданным 2м параметром именем