I've seen many people regarding them as the same,like unnamed(anonymous) namespace definition
However,there actually seems to be some difference between them,like Are “anonymous structs” standard? And, really, what are they?
As far as I'm concerned,both of them have no name,it seems hard to me to distinguish them from the semantic.
For example,the lambda is a unnamed object of an unnamed class,can we just say lambda is a anonymous object of an anonymous class?
Related
If it's an ordinary local object, its scope begins when it's declared, and things before its declaration can't access it. However, if it's a member variable, then anything in this class, even written before the declaration of that member, has access to it.
What happens under the hood? Why is it designed this way?
I tried to google about it but only got the rule itself instead of the mechanism or the motive.
There's nothing to answer here. It is just that way.
Under the hood happens that the compiler tracks the scope as specified by the language.
Why that language is that way: I'd say it is intuitive, but you seem to disagree, so the only argument I could come up with has been devalued by the very question you're asking. 🤷🏼.
We had a function that used a non-capturing lambda internal to itself, e.g.:
void foo() {
auto bar = [](int a, int b){ return a + b; }
// code using bar(x,y) a bunch of times
}
Now the functionality implemented by the lambda became needed elsewhere, so I am going to lift the lambda out of foo() into the global/namespace scope. I can either leave it as a lambda, making it a copy-paste option, or change it to a proper function:
auto bar = [](int a, int b){ return a + b; } // option 1
int bar(int a, int b){ return a + b; } // option 2
void foo() {
// code using bar(x,y) a bunch of times
}
Changing it to a proper function is trivial, but it made me wonder if there is some reason not to leave it as a lambda? Is there any reason not to just use lambdas everywhere instead of "regular" global functions?
There's one very important reason not to use global lambdas: because it's not normal.
C++'s regular function syntax has been around since the days of C. Programmers have known for decades what said syntax means and how they work (though admittedly that whole function-to-pointer decay thing sometimes bites even seasoned programmers). If a C++ programmer of any skill level beyond "utter newbie" sees a function definition, they know what they're getting.
A global lambda is a different beast altogether. It has different behavior from a regular function. Lambdas are objects, while functions are not. They have a type, but that type is distinct from the type of their function. And so forth.
So now, you've raised the bar in communicating with other programmers. A C++ programmer needs to understand lambdas if they're going to understand what this function is doing. And yes, this is 2019, so a decent C++ programmer should have an idea what a lambda looks like. But it is still a higher bar.
And even if they understand it, the question on that programmer's mind will be... why did the writer of this code write it that way? And if you don't have a good answer for that question (for example, because you explicitly want to forbid overloading and ADL, as in Ranges customization points), then you should use the common mechanism.
Prefer expected solutions to novel ones where appropriate. Use the least complicated method of getting your point across.
I can think of a few reasons you'd want to avoid global lambdas as drop-in replacements for regular functions:
regular functions can be overloaded; lambdas cannot (there are techniques to simulate this, however)
Despite the fact that they are function-like, even a non-capturing lambda like this will occupy memory (generally 1 byte for non-capturing).
as pointed out in the comments, modern compilers will optimize this storage away under the as-if rule
"Why shouldn't I use lambdas to replace stateful functors (classes)?"
classes simply have fewer restrictions than lambdas and should therefore be the first thing you reach for
(public/private data, overloading, helper methods, etc.)
if the lambda has state, then it is all the more difficult to reason about when it becomes global.
We should prefer to create an instance of a class at the narrowest possible scope
it's already difficult to convert a non-capturing lambda into a function pointer, and it is impossible for a lambda that specifies anything in its capture.
classes give us a straightforward way to create function pointers, and they're also what many programmers are more comfortable with
Lambdas with any capture cannot be default-constructed (in C++20. Previously there was no default constructor in any case)
Is there any reason not to just use lambdas everywhere instead of "regular" global functions?
A problem of a certain level of complexity requires a solution of at least the same complexity. But if there is a less complex solution for the same problem, then there is really no justification for using the more complex one. Why introduce complexity you don't need?
Between a lambda and a function, a function is simply the less complex kind of entity of the two. You don't have to justify not using a lambda. You have to justify using one. A lambda expression introduces a closure type, which is an unnamed class type with all the usual special member functions, a function call operator, and, in this case, an implicit conversion operator to function pointer, and creates an object of that type. Copy-initializing a global variable from a lambda expression simply does a lot more than just defining a function. It defines a class type with six implicitly-declared functions, defines two more operator functions, and creates an object. The compiler has to do a lot more. If you don't need any of the features of a lambda, then don't use a lambda…
After asking, I thought of a reason to not do this: Since these are variables, they are prone to Static Initialization Order Fiasco (https://isocpp.org/wiki/faq/ctors#static-init-order), which could cause bugs down the line.
if there is some reason not to leave it as a lambda? Is there any reason not to just use lambdas everywhere instead of "regular" global functions?
We used to use functions instead of global functor, so it breaks the coherency and the Principle of least astonishment.
The main differences are:
functions can be overloaded, whereas functors cannot.
functions can be found with ADL, not functors.
Lambdas are anonymous functions.
If you are using a named lambda, it means you are basically using a named anonymous function. To avoid this oxymoron, you might as well use a function.
Suppose I have a class whose only purpose is the side-effects caused during construction of its objects (e.g., registering a class with a factory):
class SideEffectCauser {
public:
SideEffectCauser() { /* code causing side-effects */ }
};
Also suppose I'd like to have an object create such side-effects once for each of several translation units. For each such translation unit, I'd like to be able to just put an a SideEffectCauser object at namespace scope in the .cpp file, e.g.,
SideEffectCauser dummyGlobal;
but 3.6.2/3 of the C++03 standard suggests that this object need not be constructed at all unless an object or function in the .cpp file is used, and articles such as this and online discussions such as this suggest that such objects are sometimes not initialized.
On the other hand, Is there a way to instantiate objects from a string holding their class name? has a solution that is claimed to work, and I note that it's based on using an object of a type like SideEffectCauser as a static data member, not as a global, e.g.,
class Holder {
static SideEffectHolder dummyInClass;
};
SideEffectHolder Holder::dummyInClass;
Both dummyGlobal and dummyInClass are non-local statics, but a closer look at 3.6.2/3 of the C++03 standard shows that that passage applies only to objects at namespace scope. I can't actually find anything in the C++03 standard that says when non-local statics at class scope are dynamically initialized, though 9.4.2/7 suggests that the same rules apply to them as to non-local statics at namespace scope.
Question 1: In C++03, is there any reason to believe that dummyInClass is any more likely to be initialized than dummyGlobal? Or may both go uninitialized if no functions or objects in the same translation unit are used?
Question 2: Does anything change in C++11? The wording in 3.6.2 and 9.4.2 is not the same as the C++03 versions, but, from what I can tell, there is no behavioral difference specified for the scenarios I describe above.
Question 3: Is there a reliable way to use objects of a class like SideEffectHolder outside a function body to force side-effects to take place?
I think the only reliable solution is to design this for specific compiler(s) and runtime. No standard covers the initialization of globals in a shared library which I think is the most intricate case, as this is much dependent on the loader and thus OS dependent.
Q1: No
Q2: Not in any practical sense
Q3: Not in a standard way
I'm using something similar with g++ / C++11 under Linux and get my factories registered as expected. I'm not sure why you wouldn't get the functions called. If what you describes is to be implemented it will mean that every single function in that unit has to call the initialization function. I'm not too sure how that could be done. My factories are also inside namespaces, although it is named namespaces. But I don't see why it wouldn't be called.
namespace snap {
namespace plugin_name {
class plugin_name_factory {
public:
plugin_name_factory() { plugin_register(this, name); }
...
} g_plugin_name_factory;
}
}
Note that the static keyword should not be used anymore in C++ anyway. It is often slower to have a static definition than a global.
This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
Superiority of unnamed namespace over static?
Why unnamed namespace is a“ superior” alternative to static?
I know know anonymous namespaces are "encouraged" over static globals which are more C like (and deprecated), etc etc, and I use them often myself. However, despite having read other posts and questions about this topic, I haven't really seen explicit reasons why an anonymous namespace is better than a set of simple static globals.
Is there a definite reason why I should stick to the former?
Static variables at namespace scope are no longer deprecated.
There's no particular reason to prefer one over the other. A minor reason to prefer an unnamed namespace is that you can declare anything inside it, while only functions and variables can be static. A minor reason to prefer static declarations is that you don't have extra braces loitering around the declaration. Use whichever feels more harmonious to you.
Historical note: before C++11, there was one reason to prefer a namespace: for some bizarre reason, pointers to static objects or functions could not be used as template arguments, while pointers to non-static ones could. C++11 removes this restriction, along with the equally odd restrictions preventing, for example, local types being template arguments.
This question already has answers here:
Superiority of unnamed namespace over static?
(2 answers)
Closed 9 years ago.
The section $7.3.1.1/2 from the C++ Standard reads:
The use of the static keyword is
deprecated when declaring objects in a
namespace scope; the unnamed-namespace
provides a superior alternative.
I don't understand why an unnamed namespace is considered a superior alternative? What is the rationale? I've known for a long time as to what the standard says, but I've never seriously thought about it, even when I was replying to this question: Superiority of unnamed namespace over static?
Is it considered superior because it can be applied to user-defined types as well, as I described in my answer? Or is there some other reason as well, that I'm unaware of? I'm asking this, particularly because that is my reasoning in my answer, while the standard might have something else in mind.
As you've mentioned, namespace works for anything, not just for functions and objects.
As Greg has pointed out, static means too many things already.
Namespaces provide a uniform and consistent way of controlling visibility at the global scope. You don't have to use different tools for the same thing.
When using an anonymous namespace, the function/object name will get mangled properly, which allows you to see something like "(anonymous namespace)::xyz" in the symbol table after de-mangling, and not just "xyz" with static linkage.
As pointed out in the comments below, it isn't allowed to use static things as template arguments, while with anonymous namespaces it's fine.
More? Probably, but I can't think of anything else right now.
One reason may be that static already has too many meanings (I can count at least three). Since an anonymous namespace can encapsulate anything including types, it seems superior to the static solution.
There are two reasons I think:
static has two different meanings: at class scope, it means shared by the whole class while at file/function scope it affects the visibility/storage...
unnamed namespaces allow to declare new struct, class and typedef
One note though, the commitee backpedaled on this: static is no longer marked as deprecated in n3225.