Defending against the danger of function name hiding class name - c++

#include <iostream>
using namespace std;
#include "other_library.h"
struct Foo
{
Foo() { cout << "class\n"; }
};
int main()
{
Foo(); // or Foo() in any expression
}
This outputs class, or so we would think. The problem is that if other_library.h happens to have a function called Foo whose return type is suitable to appear in whatever expression we used Foo in then it silently changes the behaviour, e.g.:
int Foo() { cout << "func\n"; return 1; }
causes func to be output without any code changing in main. This is bad because of the possibility for insidious and hard-to-detect bugs ; even if it is not malicious intent on the part of other_library, a name clash could go undetected.
What is a good way to deal with this problem? It was originally raised by Dan Saks in 1997, and one suggested resolution is that all classes should be typedef'd:
typedef struct Foo Foo;
as the compiler does have to report a clash between a typedef-name and a function name. However this does not appear to be common practice - why not?
Clarification: this question is about good practices for our code to stop this undetected behaviour change happening without us noticing. (As opposed to how to solve it once we have realized that it is happening, which is easier -- e.g. rename our class).

typedef struct Foo Foo;
as the compiler does have to report a clash between a typedef-name and
a function name. However this does not appear to be common practice -
why not?
I hold this truth to be self-evident: cumbersome code is cumbersome. You can actually rather easily fix this by working in a namespace of your own (which, assuming the header file is C++, too, the other_library should also do.

Unfortunately, you cannot avoid this. From C++11 standard (3.3.10):
A class name (9.1) or enumeration name (7.2) can be hidden by the name of a variable, data member, function, or enumerator declared in the same scope. If a class or enumeration name and a variable, data member, function, or enumerator are declared in the same scope (in any order) with the same name, the class or enumeration name is hidden wherever the variable, data member, function, or enumerator name is visible.
The only way to guard against it is the typedef trick you pointed out (thanks for that!), using namespaces, or adhering to naming conventions (the latter not helping when dealing with 3rd party code). You could also try to wrap the include in a namespace (shown bellow), but as the comments pointed out, this could cause link errors in certain situations.
namespace otherlib {
#include "other_library.h"
}
Then:
otherlib::Foo();

current best practises protect against this already
Naming Conventions, such as
void camelCase() vs class PascalCase
namespaces
wrapper libs for everything not modern C++

Related

Can a class name instead of a namespace be pre-pended to :: for scope resolution?

So as I understand it, when I see double colons(abc::xyz) used the thing on the left is a namespace and the thing on the right can be a function or variable of some sort that is defined in that namespace. ex. namespace::bar, namespace::foo()
Now, can the thing on the left be a class? ex. class::bar, class::foo()
If so, does anyone have any info on this. I can find lots of info of scope resolution pertaining to namespaces but not when it comes to classes.
In my situation I am going through a rather large project of code that is from another individual.
The code usage that I am trying to understand is that I have the following line of code...
multi_img::ptr input = imginput::ImgInput(config.input).execute();
On the right the imginput::ImgInput() can be found because there is a namespace imginput that I can find. But on the left, the multi_img::ptr, there is no multi_img namespace in the project. There is a multi_img class that contains the following line...
typedef boost::shared_ptr<multi_img> ptr;
I believe this is what multi_img::ptr means but can not find any documentation to back up my assumption.
Now, can the thing on the left be a class?
Yes it can, and to justify consider the following example:
#include <iostream>
class foo {
public:
void fun() const { std::cout << "foo:fun()" << std::endl; }
};
int main() {
foo f;
f.foo::fun();
return 0;
}
DEMO
Every class member lies in the scope of its class.
Edit after #Cheersandhth.-Alf constructive comment:
Thus, you can access a member through an object with either the classical way (e.g., f.fun()) in which case you'll have a virtual call or you call it like in the example (i.e., f.foo::fun()) in which case you explicitly disambiguate the scope of member function at compile time.
Yes, you can have a class name on the left of ::. It is used to denote a member of that class. The multi_img class has a member called ptr. As you have shown, that member is a typedef. That is, the type multi_img::ptr is a synonym of boost::shared_ptr<multi_img>.
Note that :: is used to access static members and nested types, since these only require the name of the class and not a particular object that of that class type. We use . and -> to access non-static data members of a particular object.
Usually the classname::member notation is used to
Access static members.
E.g. Blah::uuid.
Prevent virtual call.
E.g. in Blah::foo, a call like Base::foo().
Disambiguate.
E.g. with two bases A and B, both of which provides a foo, a call like B::foo().
Some older libraries use classes instead of namespaces. I vaguely recall an XML library and a GUI library. Not sure which.
Personally I do the class-as-faux-namespace for enumeration types, e.g.
struct Weekdays
: Non_instantiable
{
enum Enum { wednesday, friday, saturday };
};
used like
auto foo() -> Weekdays::Enum { return Weekdays::friday; }
even after C++11 started supported enum class.
Sometimed it is difficult to know whether the nested name specifier denotes a namespace or a class because the syntax is the same. Moreother the same name can denote either a namespace or a class depending on the declaration region where the name is used. For example
namespace A
{
struct A
{
static int a;
static int b;
static int c;
};
int A::a = 5;
}
int A::A::b = 10;
int A::A::c = a;
The most appropriate documentation is the C++ Standard. You may download a working draft of the Standard from the ISO-IEC site
As for the typedef that defines a type
typedef boost::shared_ptr<multi_img> ptr;
then it seems that it is defined in the class definition of multi_img. So if the name is used outside the class scope it shall be qualified
multi_img::ptr input = imginput::ImgInput(config.input).execute();

Wherefore inline unnamed namespaces?

A quick one for the gurus: C++11 allows unnamed namespaces to be declared inline. This seems redundant to me; things declared in an unnamed namespace are already used as if they were declared in the enclosing namespace.
So my question is this: what does it mean to say
inline namespace /*anonymous*/ {
// stuff
}
and how is it different from the traditional
namespace /*anonymous*/ {
// stuff
}
that we know and love from C++98? Can anyone give an example of different behaviour when inline is used?
EDIT: Just to clarify, since this question has been marked as a duplicate: I'm not asking about named inline namespaces in general. I understand the use-case there, and I think they're great. I'm specifically asking what it means to declare an unnamed namespace as inline. Since unnamed namespaces are necessarily always local to a TU, the symbol versioning rational doesn't seem to apply, so I'm curious about what adding inline actually does.
As an aside, the standard [7.3.1.1], regarding unnamed namespaces, says:
inline appears if and only if it appears in the unnamed-namespace-definition
but this seems like a tautology to my non-language lawyer eyes -- "it appears in the definition iff it appears in the definition"! For bonus points, can anyone explain what this bit of standardese is actually saying?
EDIT: Cubbi claimed the bonus point in the comments:
the standard is saying that unnamed-namespace-definition behaves as if it were replaced by X where inline appears in X iff it appears in the unnamed-namespace-definition
I don't know whether it's the done thing to answer your own question on SO, but after some playing around my curiosity has been satisfied, so I may as well share it.
The definition of an inline namespace includes not only the hoisting of names into the enclosing namespace (which happens anyway for unnamed namespaces), but also allows templates defined within an inline namespace to be specialised outside it. It turns out that this applies to unnamed namespaces too:
inline // comment this out to change behaviour
namespace {
template <typename T> struct A {};
}
template <> struct A<int> {};
Without the inline, g++ complains about trying to specialise a template from a different namespace (though Clang does not). With inline, it compiles just fine. With both compilers, anything defined within the specialisation is still marked as having internal linkage (according to nm), as if it were within the unnamed namespace, but I guess this is to be expected. I can't really think of any reason why this would be useful, but there we go.
An arguably more useful effect comes from the change regarding argument-dependent lookup for inline namespaces, which also affects unnamed inline namespaces. Consider the following case:
namespace NS {
// Pretend this is defined in some header file
template <typename T>
void func(const T&) {}
// Some type definition private to this TU
inline namespace {
struct A {};
}
} // end namespace NS
int main()
{
NS::A a;
func(a);
}
Without inline, ADL fails and we have to explicitly write NS::func(a). Of course, if we defined the unnamed namespace at the toplevel (as one normally would), then we wouldn't get ADL whether it was inline or not, but still...
Here is one use that I have found:
namespace widgets { inline namespace {
void foo();
} } // namespaces
void widgets::foo()
{
}
In this example, foo has internal linkage and we can define the function later on by using the namespace::function syntax to ensure that the function's signature is correct. If you were to not use the widgets namespace then the void foo() definition would define a totally different function. You also don't need to re-open the namespace saving you a level of indentation.
If there is another function called foo in the widgets namespace already then this will give you an ambiguity instead rather than a nasty ODR violation.

Static Variable initialisation for Classes in C++, why include data type?

I've been learning C++, and I've come across static variable (I have prior knowledge from C89), and in the resource i'm using, they've declared a static variable in a class such as:
class nameHere
{
public:
static int totalNum;
}
int nameHere::totalNum = 0;
int main()
{}
For Example.
What I don't understand is that, since I've already declared that the static variable is an integer in the class definition, why do I need to also declare it as an integer outside of the class definition?
Would it not make sense to simply initialise it like so:
nameHere::totalNum = 0;
int main()
{}
Is there a particular reason or simply a convention of C++?
Thanks for all the help!
This would (probably) make the language even more difficult to parse (and it's already almost insanely difficult to parse anyway).
As it is, the datatype (int, long, my_class, whatever) tells the compiler that what it's seeing is the beginning of a declaration (which, in this case, is also a definition). Without that, the compiler would have a rather more difficult time sorting things out.
In the specific case of things at global scope, it wouldn't be that bad, because at global scope about all you can have is a series of declarations. At any other scope, however, things would be more difficult (and having one rule at global scope, and another elsewhere would be ugly indeed).
In C++11 you can simply initialize the variable inside the class:
class nameHere
{
public:
static const int totalNum = {0};
}
There is a difference between a definition and a declaration.
While the static variable in the class has been declared, it has not been defined. The One Definition Rule, explains declarations and definitions and states
In any translation unit, a template, type, function, or object can have no more than one definition. Some of these can have any number of declarations.
Therefore, the full type of the object must be used when declaring the variable.

Scoped using-directive within a struct/class declaration? [duplicate]

This question already has answers here:
Why is "using namespace X;" not allowed at class/struct level?
(6 answers)
Closed 5 years ago.
I find that my C++ header files are quite hard to read (and really tedious to type) with all the fully-qualified types (which goes as deep as 4 nested namespaces). This is the question (all the answers give messy alternatives to implementing it, but that's not the question): Is there a strong reason against introducing scoped using-directive in structs and classes in the C++ language (while it's permissible to have scoped using-declaration in functions)?
e.g.
class Foo : public Bar
{
using namespace System;
using namespace System::Network;
using namespace System::Network::Win32::Sockets;
using Bar::MemberFunc; // no conflict with this
// e.g. of how messy my header files are without scoped using-directive
void FooBar(System::Network::Win32::Sockets::Handle handle, System::Network::Win32::Sockets::Error& error /*, more fully-qualified param declarations... */);
};
Since namespace is a keyword, I would've thought it's distinct enough to cause no conflict with the scoped using declaration such as Bar::MemberFunc.
EDIT: Read the question carefully ---> I've bolded it. Reminder: we're not discussing how to improve readability of the example here. Suggesting how scoped using-directive could be implemented (i.e. by means of adding keywords / constructs etc.) in the C++ language is NOT an answer (if you could find an elegant way to implement this using existing C++ language standards, then it would of course be an answer)!
Sometimes I do this to achieve almost the same effect:
namespace detail {
using namespace System;
using namespace System::Network;
using namespace System::Network::Win32::Sockets;
class Foo : public Bar
{
void FooBar(Handle handle, Error& error);
};
}
using detail::Foo;
Given that using declarations at class scope are not inherited, this could work. The name would only be valid inside that class declaration, or inside the declarations of nested classes. But I think it's sort of overloading the concept of a class with an idea that should be larger.
In Java and Python individual files are treated in a special way. You can have import declarations that inject names from other namespaces into the file. These names will (well, not exactly with Python, but it's too complicated to explain here) only be visible within that file.
To me that argues for this sort of ability not being tied to a class declaration, but given a scope of its own instead. This would allow injected names to be used in several class declarations if it made sense, or even in function definitions.
Here is an idea I prefer because it allows these things while still giving you the benefits of a class level using declaration:
using {
// A 'using' block is a sort of way to fence names in. The only names
// that escape the confines of a using block are names that are not
// aliases for other things, not even for things that don't have names
// of their own. These are things like the declarations for new
// classes, enums, structs, global functions or global variables.
// New, non-alias names will be treated as if they were declared in
// the scope in which the 'using' block appeared.
using namespace ::std;
using ::mynamespace::mytype_t;
namespace mn = ::mynamespace;
using ::mynamespace::myfunc;
class AClass {
public:
AClass(const string &st, mytype_t me) : st_(st), me_(me) {
myfunc(&me_);
}
private:
const string st_;
mn::mytype_t me_;
};
// The effects of all typedefs, using declarations, and namespace
// aliases that were introduced at the level of this block go away
// here. typedefs and using declarations inside of nested classes
// or namespace declarations do not go away.
} // end using.
// Legal because AClass is treated as having been declared in this
// scope.
AClass a("Fred", ::mynamespace::mytype_t(5));
// Not legal, alias mn no longer exists.
AClass b("Fred", mn::mytype_t);
// Not legal, the unqualified name myfunc no longer exists.
AClass c("Fred", myfunc(::mynamespace::mytype_t(5));
This is analogous to declaring a block for local variables in a function. But in this case you are declaring a very limited scope in which you will be changing the name lookup rules.
Maybe namespace alias?
namespace MyScope = System::Network::Win32::Sockets;
You can use a typedef inside the class declaration to achieve the same
class Foo : public Bar
{
typedef System::Network::Win32::Sockets::Handle Handle;
typedef System::Network::Win32::Sockets::Error Error;
void FooBar(Handle handle, Error& error);
};
The obvious benefit of namespaces is that they allow you to avoid naming conflicts. However, by introducing an entire namespace into a class declaration, this benefit is voided. It's entirely possible that a function in the System namespace could conflict with your own Bar::MemberFunc function. You even note this in your sample code when you added the comment "no conflict with this".
You obviously don't want to introduce entire namespaces into your class like this:
using namespace System;
using namespace System::Network;
using namespace System::Network::Win32::Sockets;
And you can't add more narrowly scoped using statements like this into a class declaration. Putting these directly into a class declaration is illegal.
using System::Network::Win32::Sockets::Handle;
using System::Network::Win32::Sockets::Error;
What you can do is use the unnamed namespace. So, your header file would look something like this:
namespace {
using System::Network::Win32::Sockets::Handle;
using System::Network::Win32::Sockets::Error;
}
class Foo : public Bar
{
using Bar::MemberFunc;
// clean!
void FooBar(Handle handle, Error& error /*, more declarations*/);
};
This has three distinct advantages.
The contents of entire namespaces are not introduced. This helps to more easily avoid naming conflicts.
You have a list, before your class declaration, of what your class depends upon to work correctly.
Your function declarations are clean.
Please correct me if I'm wrong; I only briefly tested this. Quickly wrote up an example, and it compiled.

What does it mean if a method call starts with two colons?

A coworker routinely writes something like this:
::someObject->someMethod(anAttribute, anotherAttribute);
someObject is a global variable.
Those two colons seem strange to me. The code compiles and runs just fine without them.
The coworker claims that those colons make someObject explicitly global and thus prevent confusion with a possible local someObject. I would think that you would not be able to define someObject locally if it was already defined globally?
Could you shed some light on what those colons mean and whether they are necessary?
Your coworker is right. You can indeed define a local someObject which would hide the global someObject within that scope:
SomeClass* someObject = ...;
// here the global object is visible
someObject->someMethod(anAttribute, anotherAttribute); // calls the global object
void someMethod() {
SomeClass* someObject = ...;
// here the local object hides the global
::someObject->someMethod(anAttribute, anotherAttribute); // calls the global object
someObject->someMethod(anAttribute, anotherAttribute); // calls the local object
}
// here again only the global object is visible
someObject->someMethod(anAttribute, anotherAttribute); // calls the global object
Scopes can be embedded within other scopes recursively, thus you may have a namespace within global scope, a class within a namespace, an inner class within the class, a method within an inner class, a block within the method... etc. And you may have variables/classes/methods/... of identical names in any of these scopes. So identifying what entity a specific name is referring to is not a trivial task in C++. It is known as name lookup.
In brief, whenever the compiler finds a name, it looks up that name starting from the innermost scope. I.e. inside someMethod, the name someObject is matched by the object defined locally. ::someObject overrides this default behaviour and makes the compiler search only within the outermost (global) scope, thus it finds the global object instead ofthe local.
You can indeed define a someObject locally even though there is a global one. The two variables have different scope, so the compiler knows there's a difference between the two, and the double colons let you refer to the global one.
This also applies to classes outside of a namespace; i.e., to refer to a class Foo from the class Bar::Foo, you use ::Foo to tell the compiler you are talking about the one that isn't in a namespace.
Here's an example that shows it working:
#include<stdio.h>
int someInt = 4;
int main() {
int someInt = 5;
printf("%d", someInt+::someInt);
return 0;
}
If you compile and run that piece of code, it will output 9.
The coworker claims that those colons
make someObject explicitly global and
thus prevent confusion with a possible
local someObject.
Yes - it means the function can be, and must only be, matched in the global namespace. It makes it obvious you're dealing with a global, and would prevent accidental matching against something more local (beit function local, an object member, namespace member, in a namespace you're using, a Koenig lookup match etc.).
I would think that you would not be
able to define someObject locally if
it was already defined globally?
It would be a very bad idea to make it an error. Say a team of programmers decides they want to add a variable called "last_error" to their namespace: they shouldn't have to worry if existing functions in the namespace use the same name for a local variable. If you copy a function from one namespace or class to another, you shouldn't have to make error-prone identifier substitutions in the implementation.
Regarding the benefits of ::, consider:
namespace X
{
void fn() {
rip(data, bytes); // MP3 rip this data
}
}
...then fn() needs to be moved quickly into namespace Y...
namespace Y
{
void rip(const char* message, int exit_code); /* for fatal errors */
...
}
...a casual copy-paste into the guts of Y could easily overlook that log won't match the same global function it used to when fn was in namespace X, but - as illustrated - the functionality may differ markedly :-).
You can think of each namespace, class/struct and functions forming a tree, where each level must be uniquely keyed (i.e. no same-named classes in the same namespace), but decendents are always independent of each other and their ancestors. Increasing freedom to vary independently is essential for letting many people work simultaneously on a big problem.
Could you shed some light on what
those colons mean and whether they are
necessary?
In this specific usage, the :: probably isn't strictly necessary. It adds a little protection, but makes it harder to move the variable to a more local scope later - though that's not so important because the compiler will tell you about the places that continue to refer to ::x after x is moved.
Just a minor add on to all other nice points which have come in the response.
Basically :: invokes qualified name lookup in the global namespace. However it is not guaranteed to be problem free especially in the face of indiscriminate using directives.
The code shown illustrates an important property of qualified name lookup. The point here is that namespaces nominated by using directives in the global namspace are searched. However using directives in namespaces that have the name being searched are skipped.
namespace Z{
void f(){cout << 1;}
}
namespace Y{
void f(){cout << 2;}
using namespace Y; // This namespace is not searched since 'f' is found in 'Y'
}
#if 0
namespace Z{
void f(){cout << 3;}
using namespace Y; // This namespace is not searched since 'f' is found in 'Y'
}
using namespace Z;
#endif
using namespace Y;
int main(){
::f(); // Prints 2. There is no ambiguity
}
In the code shown, if lines with the #if directive are enabled, there is an ambiguity in resolving the name 'f'.