यह देखने के लिए एक तरीका बनाने का प्रयास करने की कोशिश कर रहा है कि किसी दिए गए वर्ग में एक दिया गया फ़ंक्शन है जिसे आमंत्रित किया जा सकता है, और कुछ प्रकार देता है।कक्षा के सदस्य फ़ंक्शन
क्या मैं यहां गलत कर रहा हूं पर कोई विचार? क्या यह निर्धारित करने का कोई बेहतर तरीका है कि किसी दिए गए विधि को कक्षा के लिए आमंत्रित किया जा सकता है?
#include <string>
#include <type_traits>
#define GENERATE_HAS_MEMBER_FUNC(func, rettype) \
template<typename T, class Enable = void> struct has_##func; \
template<typename T, class U> struct has_##func : std::false_type {}; \
template<typename T> \
struct has_##func<T, \
typename std::enable_if<std::is_same< \
typename std::result_of<decltype (&T::func)(T)>::type, \
rettype>::value>::type> : std::true_type{}; \
template<class T> constexpr bool has_##func##_v = has_##func<T>::value;
GENERATE_HAS_MEMBER_FUNC(str, std::string)
GENERATE_HAS_MEMBER_FUNC(str2, std::string)
GENERATE_HAS_MEMBER_FUNC(funca, std::string)
GENERATE_HAS_MEMBER_FUNC(strK, std::string)
GENERATE_HAS_MEMBER_FUNC(fancy, std::string)
GENERATE_HAS_MEMBER_FUNC(really, std::string)
struct A1 {
virtual std::string str() const { return ""; }
std::string strK() const { return ""; }
virtual std::string fancy()=0;
};
struct A2 : A1 {
std::string str() const override { return ""; }
std::string funca();
std::string fancy() override { return ""; }
std::string really(int a=0) const { return std::to_string(a); }
};
int main() {
static_assert(has_str_v<A1>,
"A1::str is virtual method with impl on base"); // MSVC: NO, clang: OK, GCC: NO
static_assert(has_strK_v<A1>,
"A1::strK is implemented inline "); // MSVC: NO, clang: OK, GCC: NO
static_assert(has_fancy_v<A1>,
"A1::fancy is a pure virtual method on base"); // MSVC: NO, clang: OK, GCC: NO
static_assert(!has_really_v<A1>,
"A1::really doesn't exist in A1"); // MSVC: OK, clang: OK, GCC: OK
static_assert(has_str_v<A2>,
"A2::str is override method "); // MSVC: OK, clang: OK, GCC: OK
static_assert(!has_str2_v<A2>,
"A2::str2 does not exist in A2"); // MSVC: NO, clang: OK, GCC: OK
static_assert(has_funca_v<A2>,
"A2::funca is defined (no impl) in A2"); // MSVC: OK, clang: OK, GCC: OK
static_assert(has_strK_v<A2>,
"A2::strK is implemented method on base"); // MSVC: OK, clang: OK, GCC: OK
static_assert(has_fancy_v<A2>,
"A1::fancy is a override of pure virtual method of base"); // MSVC: OK, clang: OK, GCC: OK
static_assert(has_really_v<A2>,
"A2::really has default param (can be invoked without params)"); // MSVC: OK, clang: NO, GCC: NO
return 0;
}
इस कार्यान्वयन पर कुछ आश्चर्य।
संपादित करें: लागू करने के लिए @ Jarod42 और @Vittorio रोमियो भयानक सुझावों को आज़माने पर:, static_assert (has_really_v:
#define GENERATE_HAS_MEMBER_FUNC(func, rettype) \
template<class T> using _has_##func_chk = \
decltype(std::declval<T &>().func()); \
template<class T> constexpr bool has_##func##_v = \
is_detected_exact_v<rettype, _has_##func_chk, T>;
अब दो टेस्ट केस अभी भी VS2015 पर असफल (किसी भी मतलब नहीं है) "ए 1 :: वास्तव में ए 1 में मौजूद नहीं है"); static_assert (! Has_str2_v, "ए 2 :: str2 ए 2 में मौजूद नहीं है");
शायद कुछ मूर्खतापूर्ण चीज है जो मुझे याद आ रही है ... कोई सुराग?
क्या आपने 'std :: is_detected' (सी ++ 17 लेकिन सी ++ 11 में लागू करने योग्य) को देखा है? – Jarod42