Unexpected behavior!

Consider the code below:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
using namespace std;

int max(double a,double b)
{
    cout << "You won't see me" << endl;
    return (a<b)?b:a;
}

int main()
{
    cout << max(3.5,3.6) << endl;// This is user made function.

    return 0;
}



Here since I am using "using namespace std;", I am expecting a name collusion Error between my max function and the standard max function, or at least the execution of the standard max function instead of my own made max function. But the program runs fine, and I am getting the message "You won't see me". Can someone explain is going on?

Thanks for reading.
C++ utilizes name mangling on functions to avoid name-clashes, so your functions are quietly hiding behind their own pseudo-namespace. Your local code also takes scope priority.

On the other hand, the C language does not have name mangling, so you wouldn't even be able to overload functions in pure C language.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#include <stdio.h>

int  printf()
{
        printf("You'll never see this");
        return 2;
}

int main()
{
        printf();
        return 0;
}

Try compiling the above with gcc and g++; g++ is perfectly happy to compile and run the new printf() function.

A namespace become crucial in libraries though;
If the two functions exist in two different external libraries and you are trying to call it from a third file, then there is no local scope to help determine a priority, so you will get a compile-time error:
header2.h:6:6: error: redefinition of ‘void out()’
6 | void out()
| ^~~
In file included from max.c:1:
header1.h:6:6: note: ‘void out()’ previously defined here
6 | void out()
Last edited on
> I am expecting a name collusion Error between my max function and the standard max function,
> or at least the execution of the standard max function instead of my own made max function.

The non-template max function is a better match. See:
4) or, if not that, F1 is a non-template function while F2 is a template specialization
https://en.cppreference.com/w/cpp/language/overload_resolution#Best_viable_function


1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>

void foo( double ) { std::cout << "non-template foo(double)\n" ; }

template < typename T >
void foo( T) { std::cout << "template foo<T>(T)\n" ; }

int main()
{
    foo( 1.2 ) ; // double : the non-template function is a better match
    foo( 1.2f ) ; // float : the template function is a better match (it does not require conversion float->double)
}

https://coliru.stacked-crooked.com/a/0219a50b6b730269
Here since I am using "using namespace std;", I am expecting a name collusion Error between my max function and the standard max function

A couple of things:

1. don't have the using directive in your code and you lessen the impact of name clashes. std::max will never be confused by the compiler with your max function if you don't have the directive.

2. what headers are you including? std::max resides in <algorithm>. It may or may not be included by other headers, that is up to the implementation. Never rely on that behavior, explicitly include whatever headers your code needs.

HINT: you should always post a Short, Self Contained, Correct (Compilable), Example that includes the includes.
http://www.sscce.org/
1. don't have the using directive in your code and you lessen the impact of name clashes. std::max will never be confused by the compiler with your max function if you don't have the directive.


This is again another extraction piece of the noobs' questions topic.
I am not anymore a fan of using namespace std; nor using directives like you said. It just that I read somewhere the following

There are lots of classes and functions in the std namespace that you may use in your
code. If you bring the std namespace into the global namespace, you will have a name
collision. For example, you can no longer use:
• function
• sort
• swap
• lock, unlock
• begin, end
• array, list, set
And those are just off the top of my head.


So I created this example to see that naming conflict with my eyes, not just with my ears!, In other way I understand the theory of it. But I want to see the experiment.

I would like also to thank @newbieg and @JLborges, I will interact your replies when i acquire more information about the language)
Last edited on
When a namespace collision happens in your code, the compiler will not allow the program to compile.
The word sounds interesting, but the code will not compile. You will just get an error message like the gray box in my post above.

I can confirm that your code here is an example of namespace collision, which is also called name clashing. -> https://cplusplus.com/forum/beginner/284764/
Last edited on
> If you bring the std namespace into the global namespace, you will have a name collision.
> For example, you can no longer use function, sort, swap

There would be an error only if there is an actual ambiguity.
For instance, this would be fine:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;

void sort( int* arr, size_t sz ) { /*std::*/sort(arr, arr + sz) ; }
void swap( int& a, int& b ) { const int temp = a ; a = b ; b = temp ; }

int main()
{
    vector<int> vector { 3, 8, 1, 5, 2 } ;
    sort( vector.data(), vector.size() ) ; // our sort
    swap( vector.front(), vector.back() ) ; // our swap
    sort( begin(vector), end(vector) ) ; // std::sort

    using function_type = void( int*, size_t ) ;
    function_type* function = sort ; // pointer to our sort
    function( vector.data(), vector.size() );
}

https://coliru.stacked-crooked.com/a/a58f1072d7c5da6c
Last edited on
Try:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <algorithm>

using namespace std;

int max(double a, double b) {
	cout << "You won't see me" << endl;
	return (a < b) ? b : a;
}

int main() {
	cout << max(4, 3) << endl;// This is user made function.

	return 0;
}


This time the params to max() are int - not double. Do you still see the message?

You shouldn't. As the type of the params are int, the std:: templated function max() is a better fit then converting the int params to double - hence the std::max() function is used.

This is function overload resolution
https://en.cppreference.com/w/cpp/language/overload_resolution
Last edited on
Hi

You should make a habit of putting your own code in it's own namespace(s) and qualify each call with that namespace. One can use a namspace alias to make that easier. Then there will be no doubt as to which function is being called. This is the reason why namespaces were invented. Also imagine a large project with multiple parts and coders, namespaces avoid the collisions.

https://en.cppreference.com/w/cpp/language/namespace_alias

Note the word collusion has a different meaning in English.
Topic archived. No new replies allowed.