 <p>As other people have said, you need to implement a comparison function yourself.</p> <p>There is a proposed way to ask the compiler to generate the obvious/naive(?) implementation: see <a href="http://www.open-std.org/Jtc1/sc22/wg21/docs/papers/2014/n4126.htm" rel="nofollow">here</a>.</p> <p>It may seem a bit unhelpful of C++ not to have already Standardised this, but often structs/classes have some <strong>data members to exclude</strong> from comparison (e.g. counters, cached results, container capacity, last operation success/error code, cursors), as well as <strong>decisions to make</strong> about myriad things including but not limited to:</p> <ul> <li>which fields to compare first, e.g. comparing a particular <code>int</code> member might eliminate 99% of unequal objects very quickly, while a <code>map&lt;string,string&gt;</code> member might often have identical entries and be relatively expensive to compare - if the values are loaded at runtime, the programmer may have insights the compiler can't possibly</li> <li>in comparing strings: case sensitivity, equivalence of whitespace and separators, escaping conventions...</li> <li>precision when comparing floats/doubles</li> <li>whether NaN floating point values should be considered equal</li> <li>comparing pointers or pointed-to-data (and if the latter, how to know how whether the pointers are to arrays and of how many objects/bytes needing comparison)</li> <li>whether order matters when comparing unsorted containers (e.g. <code>vector</code>, <code>list</code>), and if so whether it's ok to sort them in-place before comparing vs. using extra memory to sort temporaries each time a comparison is done</li> <li>how many array elements currently hold valid values that should be compared (is there a size somewhere or a sentinel?)</li> <li>which member of a <code>union</code> to compare</li> <li>normalisation: for example, date types may allow out-of-range day-of-month or month-of-year, or a rational/fraction object may have 6/8ths while another has 3/4ers, which for performance reasons they correct lazily with a separate normalisation step; you may have to decide whether to trigger a normalisation before comparison</li> <li>what to do when weak pointers aren't valid</li> <li>how to handle members and bases that don't implement <code>operator==</code> themselves (but might have <code>compare()</code> or <code>operator&lt;</code> or <code>str()</code> or getters...)</li> <li>what locks must be taken while reading/comparing data that other threads may want to update</li> </ul> <p>So, it's kind of <strong>nice to have an error</strong> until you've explicitly thought about what comparison should mean for your specific structure, <strong>rather than letting it compile but not give you a meaningful result at run-time</strong>.</p> <p>All that said, it'd be good if C++ let you say <code>bool operator==() const = default;</code> when you'd decided a "naive" member-by-member <code>==</code> test <em>was</em> ok. Same for <code>!=</code>. Given multiple members/bases, "default" <code>&lt;</code>, <code>&lt;=</code>, <code>&gt;</code>, and <code>&gt;=</code> implementations seem hopeless though - cascading on the basis of order of declaration's possible but very unlikely to be what's wanted, given conflicting imperatives for member ordering (bases being necessarily before members, grouping by accessibility, construction/destruction before dependent use). To be more widely useful, C++ would need a new data member/base annotation system to guide choices - that would be a great thing to have in the Standard though, ideally coupled with AST-based user-defined code generation... I expect it'll happen one day.</p> <h2>Typical implementation of equality operators</h2> <h3>A plausible implementation</h3> <p>It's <em>likely</em> that a reasonable and efficient implementation would be:</p> <pre><code>inline bool operator==(const MyStruct1&amp; lhs, const MyStruct1&amp; rhs) { return lhs.my_struct2 == rhs.my_struct2 &amp;&amp; lhs.an_int == rhs.an_int; } </code></pre> <p>Note that this needs an <code>operator==</code> for <code>MyStruct2</code> too.</p> <p>Implications of this implementation, and alternatives, are discussed under the heading <em>Discussion of specifics of your MyStruct1</em> below.</p> <h3>A consistent approach to ==, &lt;, &gt; &lt;= etc</h3> <p>It's easy to leverage <code>std::tuple</code>'s comparison operators to compare your own class instances - just use <code>std::tie</code> to create tuples of references to fields in the desired order of comparison. Generalising my example from <a href="http://stackoverflow.com/a/37269108/410767">here</a>:</p> <pre><code>inline bool operator==(const MyStruct1&amp; lhs, const MyStruct1&amp; rhs) { return std::tie(lhs.my_struct2, lhs.an_int) == std::tie(rhs.my_struct2, rhs.an_int); } inline bool operator&lt;(const MyStruct1&amp; lhs, const MyStruct1&amp; rhs) { return std::tie(lhs.my_struct2, lhs.an_int) &lt; std::tie(rhs.my_struct2, rhs.an_int); } // ...etc... </code></pre> <p>When you "own" (i.e. can edit, a factor with corporate and 3rd party libs) the class you want to compare, and especially with C++14's preparedness to deduce function return type from the <code>return</code> statement, it's often nicer to add a "tie" member function to the class you want to be able to compare:</p> <pre><code>auto tie() const { return std::tie(my_struct1, an_int); } </code></pre> <p>Then the comparisons above simplify to:</p> <pre><code>inline bool operator==(const MyStruct1&amp; lhs, const MyStruct1&amp; rhs) { return lhs.tie() == rhs.tie(); } </code></pre> <p>If you want a fuller set of comparison operators, I suggest <a href="http://www.boost.org/doc/libs/1_60_0/libs/utility/operators.htm" rel="nofollow">boost operators</a> (search for <code>less_than_comparable</code>). If it's unsuitable for some reason, you may or may not like the idea of support macros <a href="http://coliru.stacked-crooked.com/a/957768e47b82c2c9" rel="nofollow">(online)</a>:</p> <pre><code>#define TIED_OP(STRUCT, OP, GET_FIELDS) \ inline bool operator OP(const STRUCT&amp; lhs, const STRUCT&amp; rhs) \ { \ return std::tie(GET_FIELDS(lhs)) OP std::tie(GET_FIELDS(rhs)); \ } #define TIED_COMPARISONS(STRUCT, GET_FIELDS) \ TIED_OP(STRUCT, ==, GET_FIELDS) \ TIED_OP(STRUCT, !=, GET_FIELDS) \ TIED_OP(STRUCT, &lt;, GET_FIELDS) \ TIED_OP(STRUCT, &lt;=, GET_FIELDS) \ TIED_OP(STRUCT, &gt;=, GET_FIELDS) \ TIED_OP(STRUCT, &gt;, GET_FIELDS) </code></pre> <p>...that can then be used a la...</p> <pre><code>#define MY_STRUCT_FIELDS(X) X.my_struct2, X.an_int TIED_COMPARISONS(MyStruct1, MY_STRUCT_FIELDS) </code></pre> <p>(C++14 member-tie version <a href="http://coliru.stacked-crooked.com/a/8a9990f1339df20c" rel="nofollow">here</a>)</p> <h2>Discussion of specifics of your MyStruct1</h2> <p>There are implications to the choice to provide a free-standing versus member <code>operator==()</code>...</p> <p><strong>Freestanding implementation</strong></p> <p>You have an interesting decision to make. As your class can be implicitly constructed from a <code>MyStruct2</code>, a free-standing / non-member <code>bool operator==(const MyStruct2&amp; lhs, const MyStruct2&amp; rhs)</code> function would support...</p> <pre><code>my_MyStruct2 == my_MyStruct1 </code></pre> <p>...by first creating a temporary <code>MyStruct1</code> from <code>my_myStruct2</code>, then doing the comparison. This would definitely leave <code>MyStruct1::an_int</code> set to the constructor's default parameter value of <code>-1</code>. Depending on whether you include <code>an_int</code> comparison in the implementation of your <code>operator==</code>, a <code>MyStruct1</code> might or might not compare equal to a <code>MyStruct2</code> that itself compares equal to the <code>MyStruct1</code>'s <code>my_struct_2</code> member! Further, creating a temporary <code>MyStruct1</code> can be a very inefficient operation, as it involves copying the existing <code>my_struct2</code> member to a temporary, only to throw it away after the comparison. (Of course, you could prevent this implicit construction of <code>MyStruct1</code>s for comparison by making that constructor <code>explicit</code> or removing the default value for <code>an_int</code>.)</p> <p><strong>Member implementation</strong></p> <p>If you want to avoid implicit construction of a <code>MyStruct1</code> from a <code>MyStruct2</code>, make the comparison operator a member function:</p> <pre><code>struct MyStruct1 { ... bool operator==(const MyStruct1&amp; rhs) const { return tie() == rhs.tie(); // or another approach as above } }; </code></pre> <p>Note the <code>const</code> keyword - only needed for the member implementation - advises the compiler that comparing objects doesn't modify them, so can be allowed on <code>const</code> objects.</p> <h2>Comparing the visible representations</h2> <p>Sometimes the easiest way to get the kind of comparison you want can be...</p> <pre><code> return lhs.to_string() == rhs.to_string(); </code></pre> <p>...which is often very expensive too - those <code>string</code>s painfully created just to be thrown away! For types with floating point values, comparing visible representations means the number of displayed digits determines the tolerance within which nearly-equal values are treated as equal during comparison.</p>