3

I'm using a GNU/Linux distribution with Zsh 5.0.2, Vim 7.3, and GCC 4.8.0 to learn C++.

The following code will not compile due to redefinition of the function foo:

#include <iostream>

int foo()
{
    return 0;
}

int foo()
{
    return 0;
}

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

Attempting to compile it:

» g++ -g -pedantic -std=c++11 -Wall -Wextra -Weffc++ foo.cpp -o foo
fail.cpp: In function ‘int foo()’:
fail.cpp:8:5: error: redefinition of ‘int foo()’
 int foo()
     ^
fail.cpp:3:5: error: ‘int foo()’ previously defined here
 int foo()
     ^

However, I noticed that GCC (g++, to be specific) automatically includes <time.h> without me explicitly instructing it to do so. In a program I wrote where std::time() is used but in which I forgot to #include <ctime> and use the std:: prefix this led to time() from <time.h> to be used instead of the corresponding function from <ctime>. I am curious - which time() will be used when both and are included? As far as I can tell, both have a function by that name (and both of them work in a similar or identical fashion), see:

cppreference.com: time.h time()

cppreference.com: ctime time()

Consider the following code:

#include <ctime>
#include <time.h>
#include <iostream>

int function1()
{
    using namespace std;
    cout << "function4: " << time(NULL) << endl;
    return 0;
}

int function2()
{
    using std::time;
    std::cout << "function3: " << time(NULL) << std::endl;
    return 0;
}

int function3()
{
    std::cout << "function2: " << std::time(NULL) << std::endl;
    return 0;
}

int function4()
{
    std::cout << "function1: " << time(NULL) << std::endl;
    return 0;
}

int main()
{
    function1();
    function2();
    function3();
    function4();
    return 0;
}

It may not be perfect but I hope my point gets across. Here, I explicitly included <time.h> for the sake of clarity. The first three do in the ways I'm aware of declare that the std is to be used. The fourth function simply calls time() - which to me seems like either one of the <time.h> and <ctime> variants could be called.

Question 1: Why doesn't this (function4) result in an error or a warning due to ambiguity?

Question 2: Which variant is used and what determines that one takes precedence over the other?

Question 3: Is there a way to, say, output the function name in its entirety during a run or compilation process to see what library is used?

totte
  • 87
  • 1
  • 2
  • 10

2 Answers2

10

If you look inside <ctime>, you will find the following:

#include <time.h>
namespace std
{
   using ::time;
}

This means even if you include <ctime>, it calls the one in <time.h>. Here is a link to the actual header.

Jesse Good
  • 50,901
  • 14
  • 124
  • 166
3

Note that using the C headers in C++ is deprecated; and that there's no guarantee that the C++ headers dump the definitions into the global namespace as well as std. Any answer will be fairly specific to your implementation.

Why doesn't this (function4) result in an error or a warning due to ambiguity?

For two reasons:

  • You are allowed to declare functions as may times as you like. In this implementation, most C functions only have declarations in the headers with the definitions in a precompiled library.
  • The headers have include guards, so they can safely be included more than once even if they define functions.

Which variant is used and what determines that one takes precedence over the other?

In the global namespace, it will be the version declared in the both headers; both declare the same function. In general, it's unspecified whether the C++ header also declares that function as well as the one in the std namepsace; in your implementation, it does.

Is there a way to, say, output the function name in its entirety during a run or compilation process to see what library is used?

Maybe; but there's no point since it will be the same function whichever header declares it.

Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
  • I'll need to think about this... but I realize now that `` is for C and not C++ (where `` should be used). Perhaps it was a poor example I chose, but what if, hypothetically, two different libraries were included and they each have a function with the same name... and this function was then called upon in my code without a prefix such as `foo::` to specify _which_ of the two I wanted? – totte May 27 '13 at 11:47
  • 1
    @totte: If the two functions have the same name but different signatures, then you'll get whichever matches the arguments you call it with. If they have the same signature, then you've broken the One Definition Rule and you'll get undefined behaviour; most likely, either a link error or a call to an arbitrary version of the function. – Mike Seymour May 27 '13 at 11:50
  • Would my first example (in which I declared two functions with the name `foo()`) be an example of breaking that rule? – totte May 27 '13 at 12:30
  • 1
    @totte: By *defining* them both, yes, you broke the rule; and since both definitions are in the same translation unit, the compiler can diagnose the error. You can *declare* the function as often as you like; all the declarations would refer to the same function. – Mike Seymour May 27 '13 at 12:33
  • Oops, typo. Thank you for clarifying this! – totte May 27 '13 at 12:44