Không, memcmp
không phù hợp để làm điều này. Và sự phản chiếu trong C ++ là không đủ để làm điều này vào thời điểm này (sẽ có các trình biên dịch thử nghiệm hỗ trợ sự phản chiếu đủ mạnh để thực hiện điều này và c ++ 23 có thể có các tính năng bạn cần).
Không có phản xạ tích hợp, cách dễ nhất để giải quyết vấn đề của bạn là thực hiện một số phản xạ thủ công.
Thực hiện việc này:
struct some_struct {
int x;
double d1, d2;
char c;
};
chúng tôi muốn thực hiện số lượng công việc tối thiểu để có thể so sánh hai trong số này.
Nếu chúng ta có:
auto as_tie(some_struct const& s){
return std::tie( s.x, s.d1, s.d2, s.c );
}
hoặc là
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 );
}
cho c ++ 11 , sau đó:
template<class S>
bool are_equal( S const& lhs, S const& rhs ) {
return as_tie(lhs) == as_tie(rhs);
}
làm một công việc khá tốt.
Chúng ta có thể mở rộng quá trình này để được đệ quy với một chút công việc; thay vì so sánh các mối quan hệ, hãy so sánh từng phần tử được gói trong một mẫu và mẫu đó operator==
áp dụng đệ quy quy tắc này (bao bọc phần tử as_tie
để so sánh) trừ khi phần tử đã hoạt động ==
và xử lý các mảng.
Điều này sẽ yêu cầu một chút thư viện (100 dòng mã?) Cùng với việc viết một chút dữ liệu "phản chiếu" thủ công cho mỗi thành viên. Nếu số lượng cấu trúc bạn có bị giới hạn, việc viết mã theo cấu trúc theo cách thủ công có thể dễ dàng hơn.
Có lẽ có nhiều cách để có được
REFLECT( some_struct, x, d1, d2, c )
để tạo as_tie
cấu trúc bằng cách sử dụng các macro khủng khiếp. Nhưng as_tie
đủ đơn giản. Trong c ++ 11 sự lặp lại gây khó chịu; Điều này rất hữu ích:
#define RETURNS(...) \
noexcept(noexcept(__VA_ARGS__)) \
-> decltype(__VA_ARGS__) \
{ return __VA_ARGS__; }
trong tình huống này và nhiều người khác. Với RETURNS
, viết as_tie
là:
auto as_tie(some_struct const& s)
RETURNS( std::tie( s.x, s.d1, s.d2, s.c ) )
loại bỏ sự lặp lại.
Đây là một cú đâm làm cho nó đệ quy:
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 (mảng) (đệ quy đầy đủ, thậm chí hỗ trợ các mảng của mảng):
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>{} ) )
Ví dụ sống .
Ở đây tôi sử dụng một std::array
số refl_tie
. Tốc độ này nhanh hơn nhiều so với bộ Refl_tie trước đây của tôi tại thời điểm biên dịch.
Cũng thế
template<class T,
typename std::enable_if< !std::is_class<T>{}, bool>::type = true
>
auto refl_tie( T const& t )
RETURNS(std::cref(t))
sử dụng std::cref
ở đây thay vì std::tie
có thể tiết kiệm chi phí thời gian biên dịch, vì đây cref
là một lớp đơn giản hơn nhiều so với tuple
.
Cuối cùng, bạn nên thêm
template<class T, std::size_t N, class...Ts>
auto refl_tie( T(&t)[N], Ts&&... ) = delete;
điều này sẽ ngăn các thành viên mảng phân rã thành các con trỏ và quay trở lại sự bình đẳng con trỏ (mà bạn có thể không muốn từ các mảng).
Nếu không có điều này, nếu bạn truyền một mảng cho một cấu trúc không được phản ánh, nó sẽ rơi vào cấu trúc con trỏ đến không phản xạ refl_tie
, hoạt động và trả về vô nghĩa.
Với điều này, bạn kết thúc với một lỗi thời gian biên dịch.
Hỗ trợ đệ quy thông qua các loại thư viện là khó khăn. Bạn có thể std::tie
họ:
template<class T, class A>
auto refl_tie( std::vector<T, A> const& v )
RETURNS( std::tie(v) )
nhưng điều đó không hỗ trợ đệ quy thông qua nó.