Talk:cpp/language/cast operator
Note: I have added the same discussion to this page http://en.cppreference.com/w/Talk:cpp/language/friend
Not sure where it fits best (if at all)
I see you have operators, an example of conversions may be helpful too?
From discussion @ stackoverflow
http://stackoverflow.com/questions/41141119/c-friend-conversion-function
class t_conversion_helpers { public: operator char ( ) ; }; class t_friend_conversion_example { public: friend t_conversion_helpers::operator char ( ) ; };
86.140.194.68 01:32, 15 December 2016 (PST)Michael Collier
- The friend A::operator B(); example was added to this page in response to that StackOverflow discussion. I don't think this larger example would demonstrate any semantics for user-defined conversions that the existing examples don't already show (and it's not even using the friend relationship it installed) --Cubbi (talk) 06:34, 15 December 2016 (PST)
[edit] Where does the name lookup for types happen?
Consider the following example (https://godbolt.org/z/1f7KzbY55):
int main()
{
struct S {
using T = int;
// operator T() { return 0; }
operator int() { return 0; }
} s;
int a1 = s.operator int(); // fine
int a2 = s.S::operator int(); // fine
int b1 = s.operator S::T(); // also fine
int b2 = s.S::operator S::T(); // also fine
int c1 = s.operator T(); // (!)
int c2 = s.S::operator T(); // (!)
// T err; // obviously fails on all compilers
}
One would expect that both c1 and c2 are ill-formed since the name T is out of their scope. And indeed clang rejects them. But as it turns out, gcc accepts both of them and msvc accepts c2. At first I thought this had something to do with the name of the conversion function (I originally discovered this situation with a function pointer type so I couldn't use the type name itself), that is, I thought gcc considered the name operator T to be the name of the function but as it turns out using either operator T or operator int in the definition lead to the exact same behaviour. So this happens only because the typedef name T is there.
In any case, my questions are: 1) What is the correct behavior? 2) How should we describe it in this page? --172.68.62.134 11:57, 3 June 2023 (PDT)
- So, it turns out I completely missed the following sentence from cpp/language/qualified_lookup: "A conversion-type-id in a user-defined conversion function name is first looked up in the scope of the class. If not found, the name is then looked up in the current scope. " This means that c2 is handled correctly by gcc and msvc. However, that still leaves c1. --172.68.62.153 12:18, 3 June 2023 (PDT)
- I think I also found the answer for c1 but I'm not sure at all about it. cpp/language/unqualified_lookup says "If explicit function call syntax is used, regular unqualified name lookup is performed" and "For a name used in the definition of a function, either in its body or as part of default argument, where the function is a member of user-declared or global namespace, the block in which the name is used is searched before the use of the name, then the enclosing block is searched before the start of that block, etc, until reaching the block that is the function body. Then the namespace in which the function is declared is searched until the definition (not necessarily the declaration) of the function that uses the name, then the enclosing namespaces, etc. ". Finally cpp/language/scope says:"The potential scope of a name declared in a class begins at the point of declaration and includes the rest of the class body, all the derived classes bodies, the function bodies (even if defined outside the class definition or before the declaration of the name), function default arguments, function exception specifications, in-class brace-or-equal initializers, and all these things in nested classes, recursively. " which I thought means T should not be visible in the scope of main, however it also says "Names of class members can be used in the following contexts:[...] after the . operator applied to an expression of the type of its class or a class derived from it" which means that T should be allowed in that context? I honestly don't know what the answer is at this point but it sounds like gcc is correct?. As a side note, I originally found this in cpp/named_req/FunctionObject when I added the example of a type convertible to a function pointer. The relevant part looks like this:
struct T {
static void bar(int x) { std::cout << "T::bar(" << x << ")\n"; }
using FP = void (*)(int);
operator FP() const { return bar; }
} t;
t.operator FP()(11); // changed to T::FP after I noticed clang rejected it. Should it be changed back?
- --172.68.62.134 12:49, 3 June 2023 (PDT)
- Of course, turns out literally all of this is known https://stackoverflow.com/questions/62221235/compiler-discrepancy-for-out-of-line-definitions-of-conversion-operators and https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2020/p1787r6.html The articles cpp/language/scope, cpp/language/unqualified_lookup, cpp/language/qualified_lookup and so on might need to be updated per that paper's changes but I haven't read it yet so I'm not sure how much of that has been done. --172.68.62.142 16:20, 3 June 2023 (PDT)
- --172.68.62.134 12:49, 3 June 2023 (PDT)