該tie
解決方案將是你最好的選擇。
struct equal_by_tie {
template<class T>
using enable = std::enable_if_t<std::is_base_of<equal_by_tie, T>,bool>;
template<class T>
friend enable<T>
operator==(T const& lhs, T const& rhs) {
return mytie(lhs) == mytie(rhs);
}
template<class T>
friend enable<T>
operator!=(T const& lhs, T const& rhs) {
return mytie(lhs) != mytie(rhs);
}
};
現在你必須寫
struct some_thing : equal_by_tie {
public:
friend auto mytie(some_thing const& self) {
return std::tie(self.x, self.y, self.mem3);
}
};
和==
和!=
是爲你寫的。
目前沒有辦法審覈mytie
是否正確寫入,除非在C++ 17中有一些誠實不值得考慮的黑客行爲(結構化綁定,它是一個可怕的黑客,不要問)。
一種方法可以減少mytie
錯誤的機會是使用它更多。
以它的方式實現swap
(也許使用與上面的operator==
相同的父類欺騙)。根據swap
或mytie
執行operator=
。對friend std::size_t hash(Foo const&)
執行相同的操作,並將其掛接到標準篩選器中。
堅持要求mytie
與您的數據聲明的順序相同,並使其與父實例綁定爲子綁定。編寫一個函數,將您的系統結構/類對齊考慮在內,並計算的結構在constexpr
中的大小。靜態聲明Foo
和calc_struct_size(tag<decltype(mytie(std::declval<Foo&>()))>)
的大小匹配。 (根據需要添加vtables或類似的軟件因素)。現在改變結構的佈局而不觸及mytie
會導致不好的事情發生。
比較mytie
中每對字段的指針不等,以確保不重複同一個字段兩次;嘗試確保在運行時優化到true
(棘手,因爲您需要在調試中執行此操作,並且調試通常關閉了優化;也許這是您希望僅在發佈時執行的斷言的唯一情況建立!)。
你也想做一些理智的檢查。如果您的mytie
包含原始指針,==
是錯誤的,並且對於智能指針是相同的;你想要你的==
是一個深刻的平等。
爲此,也許==
是錯誤的東西。
struct deep_equal_by_tie {
template<class T>
using enable = std::enable_if_t<std::is_base_of<equal_by_tie, T>,bool>;
template<class T>
friend enable<T>
deep_equal(T const& lhs, T const& rhs) {
// code to call deep_equal on each tie
// deep_equal on non-pointer basic types defined as ==
// deep_equal on pointers is to check for null (nulls are equal)
// then dereference and deep_equal
// ditto for smart pointers
// deep_equal on vectors and other std containers is to check size,
// and if matches deep_equal on elements
}
};
但是,這會增加您的負擔。但是我們的想法是增加的可靠性,正如您已經注意到的,難點在於有很多代碼和大量的錯誤點。
有沒有簡單的方法來做到這一點。
如果您的數據不是完美打包的普通舊數據而沒有指針或虛函數或任何東西,memcmp是一個壞主意。而且填充很容易滑入代碼中,從而打破了基於memcmp的平等;因爲填充中的數據狀態是未定義的,所以很難找到這樣的容器。
如果你正在考慮'memcmp()',我不會推薦'memcmp()'。 –
難道你不能將內存中的數據轉儲到文件中,然後做一個'diff'嗎? – Rakete1111
@ Rakete1111也許我可以,如果我知道如何。這就是爲什麼我問這個問題。 – johnbakers