List of C++ name resolution (and overloading) rules - c++

Where I can find a list of the rules that a C++ compliant compiler must apply in order to perform names resolution (including overloading)?
I'd like something like a natural-language algorithm or flow chart.
C++ standard of course has this set of rules but it is build up as new language statements are introduced and the result it's pretty hard to remember.
To make a long story short, I'd like to know the complete and detailed answer to the question "What compiler do when it see the name 'A'?"
I know C++ is all "We do this when X but not Y if Z holds" so, I'm asking whether it is possible to make it more linear.
EDIT: I'm working on a draft of this topic, something that may be improved collectively once posted. However i'm very busy this days and it may take time to have something publicable. If someone interested i'll promote the "personal note on a raw txt file" to something better and post it.

Well, in broad strokes:
If the name is preceded by ::, as in ::A or X::A, then use qualified name lookup. First look up X, if it exists (if not use the global namespace) then look inside it for A. If X is a class, and A is not a direct member, then look in all the direct bases of X. If A is found in more than one base, fail.
Otherwise, if the name is used as a function call such as A( X ), use argument-dependent lookup. This is the hard part. Look for A in the namespace the type of X was declared in, in the friends of X, and if X is a template instantiation, likewise for all the arguments involved. Scopes associated only by typedef do not apply. Do this in addition to unqualified lookup.
Start with unqualified lookup if argument-dependent lookup doesn't apply. This is the usual way variables are found. Start at the current scope and work outwards until the name is found. Note that this respects using namespace directives, which the other two cases do not.
Simply glancing at the Standard will reveal many exceptions and gotchas. For example, unqualified lookup is used to determine whether the name is used as a function call, as opposed to a cast-expression, before ADL is used to generate a list of potential overloads. Unqualified lookup doesn't look for objects in enclosing scopes of nested of local classes, because such objects might not exist at the time of reference.
Apply common sense, and ask more specific questions when (as often it does) intuition fails.

Related

Can Niebloids be passed where Callables is required?

Generally speaking, unless explicitly allowed, the behavior of a C++ program that tries to take the pointer of a standard library function is unspecified. Which means extra caution should be taken before passing them as Callable. Instead it is typically better to wrap them in a lambda.
More on the topic: Can I take the address of a function defined in standard library?
However, C++20 introduced Constrained algorithms, or ranged algorithms, based on the Range-v3 library; where function-like entities, such as std::ranges::sort and std::ranges::transform, are introduced as Niebloids.
While the original library has created a functor class for each functions in the algorithm library, and each niebloids, such as ranges::sort, is simply a named object of the corresponding functor class; the standard does not specify how they should be implemented.
So the question is if the behavior of passing a Niebloid as a Callable, such as std::invoke(std::ranges::sort, my_vec), specified/explicitly allowed?
All the spec says, in [algorithms.requirements] is:
The entities defined in the std​::​ranges namespace in this Clause are not found by argument-dependent name lookup ([basic.lookup.argdep]). When found by unqualified ([basic.lookup.unqual]) name lookup for the postfix-expression in a function call ([expr.call]), they inhibit argument-dependent name lookup.
The only way to implement that, today, is by making them objects. However, we don't specify any further behavior of those objects.
So this:
std::invoke(std::ranges::sort, my_vec)
will work, simply because that will simply evaluate as std::ranges::sort(my_vec) after taking a reference to it, and there's no way to really prevent that from working.
But other uses might not. For instance, std::views::transform(r, std::ranges::distance) is not specified to work, because we don't say whether std::ranges::distance is copyable or not - std::ranges::size is a customization point object, and thus copyable, but std::ranges::distance is just an algorithm.
The MSVC implementation tries to adhere aggressively to the limited specification, and its implementation of std::ranges::distance is not copyable. libstdc++, on the other hand, just makes them empty objects, so views::transform(ranges::distance) just works by way of being not actively rejected.
All of which to say is: once you get away from directly writing std::ranges::meow(r) (or otherwise writing meow(r) after a using or using namespace), you're kind of on your own.

What is the meaning of Note 1 in the C++ class member name lookup rules?

From http://eel.is/c++draft/class.member.lookup#1 :
A search in a scope X for a name N from a program point P is a single search in X for N from P unless X is the scope of a class or class template T, in which case the following steps define the result of the search.
[Note 1: The result differs only if N is a conversion-function-id or if the single search would find nothing. — end note]
I'm having a hard time making a sense of the Note. It seems that a "single search" from a class scope will find preceding declarations at namespace scope, since the namespace scope contains the class scope. But, as we know, if the name has also been declared as a member of a non-dependent base class, then the base class member takes precedence over the namespace member. Note 1 seems to contradict this, since it's basically saying "if N is not a conversion-function-id, then you can just do a normal single search, and only if you fail to find anything, then use the procedure in this section". But the single search will succeed by finding the namespace scope declaration, and the class member lookup will yield a different result.
Where is the error in my understanding?
Answer
A single search considers only one scope—not an enclosing namespace or even a base class. It’s an unqualified search that considers all enclosing scopes. Single searches and (plain) searches are subroutines of these higher-level procedures.
Context
It should be said, since there have been a lot of these questions lately, that these terms exist to reduce ambiguity and imprecision (e.g., CWG issue 191) in the definitions of “programmer-level” constructs like (un)qualified name lookup. I didn’t invent them to increase the number of vocabulary words that the typical programmer should be expected to have memorized. (Put differently, the standard is not a tutorial.)
Of course, there’s nothing special about this particular question in this regard, but I must hope that this will thereby tend to find the people that need to see it.
The purpose of a "single search" is used to state how the lookup should perform for the member. In simple, if a single search is used to find the member in the namespace's scope, its enclosing scope will not be continue found due to the single search here, if there is no declaration yet found.
As the rule you quoted here, the scope of the class or class template is an exception here to the "single search", which means the single search should continue to be performed in its base classes if nothing yet found.
The declaration set is the result of a single search in the scope of C for N from immediately after the class-specifier of C if P is in a complete-class context of C or from P otherwise.
This is a recursive procedure. Hence, the note says "The result differs only if the single search would find nothing."
Whereas for "The result differs only if N is a conversion-function-id" because of the following rule:
In each case where conversion functions of a class S are considered for initializing an object or reference of type T, the candidate functions include the result of a search for the conversion-function-id operator T in S.
It does not mean the name "operator T" is the unique name to be lookup for the conversion function, the "permissible types" are also candidates to be found according to the relevant rule.
Each such case also defines sets of permissible types for explicit and non-explicit conversion functions;
Anyway, the note is used to say the exception for a "single search" which shouldn't have found any declaration by the single search but the other candidate ways would find them.

Difference between name lookup and name binding in C++

In C++, is there a difference between name binding and name lookup in? The working draft C++14 standard (N4296) defines name lookup in (3.4) as
Name lookup associates the use of a name with a declaration (3.1) of that name.
I can't find a definition for name binding in the standard, but the IBM Knowledge Center documentation for their XL C/C++ compiler defines:
Name binding is the process of finding the declaration for each name that is explicitly or implicitly used in a template.
The only distinctions between the two definitions seem to be that (1) name binding refers specifically to a name used in a template and (2) name binding refers to a name, while name lookup refers to the use of a name.
However, Section (13.3) on Overload Resolution in the C++ standard mentions binding frequently, but without defining it. The way 'binding' is used in this context makes it seem that binding refers to the association of an argument with a function parameter.
At first, this definition seems different from either of the other two definitions, thought it fits (broadly) the definition of name lookup if we assume that the name of the function is being bound to its declaration by comparing the types of arguments and parameters. That isn't exactly the sense used in Section (13.3), but I'm trying to make sense of the standard without a proper definition.
In short, if anyone has a good definition of 'name binding' or 'binding', I'd be grateful.
Having read the relevant parts of Wilson & Clark Comparative Programming Languages, I think I have a better understanding of the topic. If I surmise correctly, the term 'binding' covers a gamut of related terms, including name-declaration binding, name–type binding, declaration-reference binding, reference-value binding, and name-value binding.
"Name lookup" seems to be a synonym for name-declaration binding. The other uses of 'binding' in the C++14 standard relate to various combinations of the other varieties of binding.
Please correct me if I'm wrong!

C++ code translation and name lookup

My question is: At what phase does the compiler perform name lookup. I think it may be when it perform semantic analysis, but I just want to make sure, since when I was searching about compiler analysis, they didn't mention name lookup in any of this phases (lexical,syntax,semantic).
In C++, name lookup generally needs to be done as part of syntax analysis (parsing), as when names are type names or template names, that affects the syntax. To the extent that things can be parsed indpendently of typenames or template names, name lookup may be deferred until later, but that's generally an implementation detail.
It's semantic analysis in general, but in C++, the stages are all intertwined, so it's understandable if someone says something else.
In C/C++, sometimes you can't decide the semantic meaning of a syntactic element, without knowing it's kind (type, variable, etc.). Most C++ compilers use generated grammar (yacc, bison) for building the syntax tree, so the name lookup must come after that.
consider the following:
A * B;
this is either the declaration of the variable B of type A *, or a statement calling operator * on it arguments A and B.

Regarding the global namespace in C++

In C++, should we be prepending stuff in the global namespace with ::?
For example, when using WinAPI, which is in C, should I do ::HANDLE instead of HANDLE, and ::LoadLibrary instead of LoadLibrary? What does C++ say about this? Is it generally a good idea, factoring in issues like readability and maintainability?
Names in C++ can be qualified and unqualified. There are different rules for qualified and unqualified name lookup. ::HANDLE is a qualified name, whereas HANDLE is an unqualified name. Consider the following example:
#include <windows.h>
int main()
{
int HANDLE;
HANDLE x; //ERROR HANDLE IS NOT A TYPE
::HANDLE y; //OK, qualified name lookup finds the global HANDLE
}
I think that the desicion of choosing HANDLE vs. ::HANDLE is a matter of coding style. Of course, as my example suggests, there might be situations where qualifying is mandatory. So, you might as well use :: just in case, unless the syntax is somewhat disgusting for you.
As namespaces don't exists in C, don't use ::HANDLE to access HANDLE type.
Using the prepending :: for global namespace is a good idea for readability, you know the type you want to access is from global namespace.
Moreover, if you are in a nested namespace and declare your own HANDLE type (for example), then the compiler will use this one instead of windows.h one!
Thus, always prefer using :: before names when working in nested namespace.
The main point of interest is what the differences are from the point of view of the compiler, as it has already been said, if you include the :: then you are using qualified lookup, rather than unqualified lookup.
The advantage of using qualified lookup is that it will be able to pinpoint a particular symbol always. The disadvantage is that it will always pinpoint that particular symbol --i.e. it will disable Argument Dependent Lookup. ADL is a big and useful part of the language, and by qualifying you effectively disable it, and that is bad.
Consider that you had a function f in the global namespace, and that you added a type T inside namespace N. Not consider that you wanted to add an overload of f that would take a T as argument. Following the interface principle, you can add f to the N namespace, as f is actually an operation performed on T, and it so belongs with the type. In this case, if you had code that called (consider generic code) ::f(obj) on an object of unknown type U the compiler will not be able to pick up ::N::f(obj) as a potential overload as the code is explicitly asking for an overload in the global namespace.
Using unqualified lookup gives you the freedom of defining the functions where they belong, together with the types that are used as arguments. While it is not exactly the same, consider the use of swap, if you qualify std::swap then it will not pick up your hand rolled void swap( T&, T& ) inside your N namespace...
I would only fully qualify identifiers when the compiler would otherwise not pick up the element I want.
It's largely a matter of style; there are no performance or efficiency concerns to speak of. It can be a good practice on large projects and projects intended to be compiled on many different platforms, as under these circumstances collisions between global names and names in a namespace are more likely to occur.
Normally, you do not have to prepend :: for the global namespace. (Only in some really rare circumstances). IMHO it harms readability, but, on the other hand it probably won't break your code
I put all of my code into a namespace, and I tend to prefer the C++ headers over the C headers, so the only symbols left in the global namespace tend to be from the Windows API. I avoid pulling symbols from other namespaces into the current namespace (e.g., I never have using namespace std;), preferring instead to qualify things explicitly. This is in line with Google's C++ style guide.
I've therefore gotten into the habit of qualifying WinAPI function calls with :: for a few reasons:
Consistency. For everything outside the current namespace, I refer to it explicitly (e.g., std::string), so why not refer to the Windows APIs explicitly (e.g., ::LoadLibraryW)? The Windows APIs namespace is the global namespace.
A lot of the WinAPI functions are named generically (e.g., DeleteObject). Unless you're very familiar with the code you're reading, you may not know whether DeleteObject is a call to something in the current namespace or to the Windows API. Thus, I find the :: clarifies.
A lot of Windows frameworks have methods with the same names as the raw calls. For example, ATL::CWindow has a GetClientRect method with a slightly different signature than WinAPI's GetClientRect. In this framework, it's common for your class to be derived from ATL::CWindow, so, in your class's implementation, it's normal to say GetClientRect to invoke the inherited ATL method and ::GetClientRect if you need to call the WinAPI function. It's not strictly necessary, since the compiler will find the right one based on the signature. Nevertheless, I find that the distinction clarifies for the reader.
(I know the question wasn't really about WinAPI, but the example was in terms of WinAPI.)
No, if you do not have a LoadLibrary method in your class you do not need to use the global scope. In fact, you should not use global scope because if you later on add a LoadLibrary to your class your intentions is probably to override the global function...