नहीं, memcmp
ऐसा करने के लिए उपयुक्त नहीं है। और C ++ में प्रतिबिंब इस बिंदु पर ऐसा करने के लिए अपर्याप्त है (ऐसे प्रायोगिक संकलक होने जा रहे हैं जो प्रतिबिंब का समर्थन करते हैं जो पहले से ही ऐसा करने के लिए पर्याप्त मजबूत है, और c ++ 23 में आपके लिए आवश्यक विशेषताएं हो सकती हैं)।
अंतर्निहित प्रतिबिंब के बिना, आपकी समस्या को हल करने का सबसे आसान तरीका कुछ मैनुअल प्रतिबिंब करना है।
इसे लो:
struct some_struct {
int x;
double d1, d2;
char c;
};
हम कम से कम काम करना चाहते हैं ताकि हम इनमें से दो की तुलना कर सकें।
अगर हमारे पास है:
auto as_tie(some_struct const& s){
return std::tie( s.x, s.d1, s.d2, s.c );
}
या
auto as_tie(some_struct const& s)
-> decltype(std::tie( s.x, s.d1, s.d2, s.c ))
{
return std::tie( s.x, s.d1, s.d2, s.c );
}
के लिए c ++ 11 है, तो:
template<class S>
bool are_equal( S const& lhs, S const& rhs ) {
return as_tie(lhs) == as_tie(rhs);
}
बहुत अच्छा काम करता है।
हम इस प्रक्रिया को थोड़ा काम के साथ पुनरावर्ती होने के लिए विस्तारित कर सकते हैं; संबंधों की तुलना करने के बजाय, टेम्पलेट में लिपटे प्रत्येक तत्व की तुलना करें, और उस टेम्पलेट का operator==
पुनरावर्ती इस नियम को लागू करता है ( as_tie
तुलना करने के लिए तत्व को लपेटता है ) जब तक कि तत्व में पहले से ही काम नहीं होता है ==
, और सरणियों को संभालता है।
इसके लिए थोड़ी सी लाइब्रेरी (कोड की 100ish लाइनें) की आवश्यकता होगी, साथ में प्रति मैनुअल "प्रतिबिंब" डेटा का एक सा लिखने के साथ। यदि आपके पास मौजूद संरचनाओं की संख्या सीमित है, तो मैन्युअल रूप से प्रति-संरचना कोड लिखना आसान हो सकता है।
शायद पाने के तरीके हैं
REFLECT( some_struct, x, d1, d2, c )
as_tie
भयानक मैक्रोज़ का उपयोग करके संरचना उत्पन्न करना । लेकिन as_tie
काफी सरल है। में ++ सी 11 पुनरावृत्ति कष्टप्रद है, यह उपयोगी है:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
इस स्थिति में और कई अन्य। के साथ RETURNS
, लेखन as_tie
है:
auto as_tie(some_struct const& s)
RETURNS( std::tie( s.x, s.d1, s.d2, s.c ) )
पुनरावृत्ति को दूर करना।
यहाँ यह पुनरावर्ती बनाने में एक छुरा है:
template<class T,
typename std::enable_if< !std::is_class<T>{}, bool>::type = true
>
auto refl_tie( T const& t )
RETURNS(std::tie(t))
template<class...Ts,
typename std::enable_if< (sizeof...(Ts) > 1), bool>::type = true
>
auto refl_tie( Ts const&... ts )
RETURNS(std::make_tuple(refl_tie(ts)...))
template<class T, std::size_t N>
auto refl_tie( T const(&t)[N] ) {
// lots of work in C++11 to support this case, todo.
// in C++17 I could just make a tie of each of the N elements of the array?
// in C++11 I might write a custom struct that supports an array
// reference/pointer of fixed size and implements =, ==, !=, <, etc.
}
struct foo {
int x;
};
struct bar {
foo f1, f2;
};
auto refl_tie( foo const& s )
RETURNS( refl_tie( s.x ) )
auto refl_tie( bar const& s )
RETURNS( refl_tie( s.f1, s.f2 ) )
c ++ 17 refl_tie (सरणी) (पूरी तरह से पुनरावर्ती, यहां तक कि सरणियों-सरणियों का समर्थन करता है):
template<class T, std::size_t N, std::size_t...Is>
auto array_refl( T const(&t)[N], std::index_sequence<Is...> )
RETURNS( std::array<decltype( refl_tie(t[0]) ), N>{ refl_tie( t[Is] )... } )
template<class T, std::size_t N>
auto refl_tie( T(&t)[N] )
RETURNS( array_refl( t, std::make_index_sequence<N>{} ) )
जीवंत उदाहरण ।
यहां मैं एक std::array
का उपयोग करता हूं refl_tie
। यह संकलन समय पर मेरे पिछले टपल ऑफ रिफ्ल_टी से बहुत तेज है।
भी
template<class T,
typename std::enable_if< !std::is_class<T>{}, bool>::type = true
>
auto refl_tie( T const& t )
RETURNS(std::cref(t))
कम्पाइल-टाइम ओवरहेड पर बचाने के std::cref
बजाय यहां उपयोग करना std::tie
, जैसा cref
कि एक बहुत सरल वर्ग है tuple
।
अंत में, आपको जोड़ना चाहिए
template<class T, std::size_t N, class...Ts>
auto refl_tie( T(&t)[N], Ts&&... ) = delete;
जो एरे सदस्यों को पॉइंटर्स को क्षय करने और पॉइंटर-इक्वैलिटी पर वापस गिरने से रोकेगा (जो आप एरे से नहीं चाहते हैं)।
इसके बिना, यदि आप किसी गैर-प्रतिबिंबित संरचना में एक सरणी पास करते हैं, तो यह सूचक से गैर-प्रतिबिंबित संरचना पर वापस गिरता है refl_tie
, जो काम करता है और बकवास करता है।
इसके साथ, आप एक संकलन-समय त्रुटि के साथ समाप्त होते हैं।
पुस्तकालय प्रकारों के माध्यम से पुनरावृत्ति के लिए समर्थन मुश्किल है। आप std::tie
उन्हें कर सकते हैं:
template<class T, class A>
auto refl_tie( std::vector<T, A> const& v )
RETURNS( std::tie(v) )
लेकिन इसके माध्यम से पुनरावृत्ति का समर्थन नहीं करता है।