#include #include //string template struct String { struct iterator { using value_type = Data; std::string::iterator d_iter; // Note the <>: operator== is a function template // specialization as 'iterator' is a class template friend bool operator==<>(iterator const &lhs, iterator const &rhs); }; iterator begin() { return iterator{}; } }; //= // The following concept checks that Type is Storage::iterator, pretty // much like a function template with parameter Storage::iterator would // do. We can't do the latter, but concept-defined types can be used. The // concept also makes is superfluous to define specific types in the nested // class which are used to select the matching free operator. The // concept-based approach cannot accidentally be broken by the user defining // identical specific types as the concepts approach simply uses the // templates' types themselves. //concept template concept StringIterator = std::same_as::iterator>; //= //operator inline bool operator==(StringIterator auto const &lhs, StringIterator auto const &rhs) { return lhs.d_iter == rhs.d_iter; } //= // template // inline bool operator==(Param const &lhs, // Param const &rhs) // { // return lhs.d_iter == rhs.d_iter; // } int main() { String str; return str.begin() == str.begin(); }