 <p>"Why is the compiler not allowed to see"</p> <p>I don't have an answer for safe bool, but I can do this bit. It's because a conversion sequence can include at most 1 user-defined conversion (13.3.3.1.2).</p> <p>As for why <em>that</em> is - I think someone decided that it would be too hard to figure out implicit conversions if they could have arbitrarily many user-defined conversions. The difficulty it introduces is that you can't write a class with a conversion, that "behaves like built-in types". If you write a class which, used idiomatically, "spends" the one user-defined conversion, then users of that class don't have it to "spend".</p> <p>Not that you could exactly match the conversion behaviour of built-in types anyway, since in general there's no way to specify the rank of your conversion to match the rank of the conversion of the type you're imitating.</p> <p>Edit: A slight modification of your first version:</p> <pre><code>#define someCondition true struct safe_bool_thing { int b; }; typedef int safe_bool_thing::* bool_type; bool_type safe_bool( const bool b ) { return b ? &amp;safe_bool_thing::b : 0; } class MyTestableClass { public: operator bool_type () const { return safe_bool( someCondition ); } private: bool operator==(const MyTestableClass &amp;rhs); bool operator!=(const MyTestableClass &amp;rhs); }; int main() { MyTestableClass a; MyTestableClass b; a == b; } </code></pre> <p><code>a == b</code> will not compile, because function overload resolution ignores accessibility. Accessibility is only tested once the correct function is chosen. In this case the correct function is <code>MyTestableClass::operator==(const MyTestableClass &amp;)</code>, which is private.</p> <p>Inside the class, <code>a == b</code> should compile but not link.</p> <p>I'm not sure if <code>==</code> and <code>!=</code> are all the operators you need to overload, though, is there anything else you can do with a pointer to data member? This could get bloated. It's no better really than Bart's answer, I just mention it because your first attempt was close to working.</p>