https://quuxplusone.github.io/blog/2021/01/13/conversion-operator-lookup/ [pumpkin-to] Arthur O'Dwyer Stuff mostly about C++ Recent Date Tag About Fun with conversion-operator name lookup As of this writing (but perhaps not for very much longer!) the four mainstream compilers on Godbolt Compiler Explorer give four different answers for this simple C++ program: struct A { using T = T1; using U = U1; operator U1 T1::*(); operator U1 T2::*(); operator U2 T1::*(); operator U2 T2::*(); }; inline auto which(U1 T1::*) { return "gcc"; } inline auto which(U1 T2::*) { return "icc"; } inline auto which(U2 T1::*) { return "msvc"; } inline auto which(U2 T2::*) { return "clang"; } int main() { A a; using T = T2; using U = U2; puts(which(a.operator U T::*())); } The question is whether U should be looked up in the scope of test or in the scope of A; and the same question for T. According to the current draft standard, it sounds like the conforming answer is "they should both be looked up in the scope of A"; i.e., GCC's answer is correct and the others are wrong in three different ways. [basic.lookup.unqual]/5: An unqualified name that is a component name of a type-specifier or ptr-operator of a conversion-type-id is looked up in the same fashion as the conversion-function-id in which it appears. If that lookup finds nothing, it undergoes unqualified name lookup; in each case, only names that denote types or templates whose specializations are types are considered. I'm never a fan of lookups that don't consider certain kinds of names; I'm sure there's more divergence to be discovered in this area. Anyway, in the type name U T::*, U is the type-specifier and T::* is the ptr-operator, and the whole type is pronounced "pointer to a data member of T, where that data member itself is of type U." (More concisely: "pointer to data member (of type U) of T," or "pointer to a U member of T.") See also: * "Implementation divergence with friend" (2019-09-10) Posted 2021-01-13 implementation-divergence name-lookup