1

I was reading about internal and external linkage, and I found that by default a function has an external linkage.

So I was thinking if is it possible to declare a function in a header filer and provide multiple definitions of it in different Translation units.

So far I did declare a funtion in a header file

void fct();

and provide 2 definitions in two files each of which is contained into an anonymous namespace:

namespace
{
    void fct()
    {    
    }    
}

But I didn't see how this could be a good examle of using multiple definitions of a function in different TU.

could someone show me a simple example of that (even using inline) thank you

Jarod42
  • 203,559
  • 14
  • 181
  • 302
Blood-HaZaRd
  • 2,049
  • 2
  • 20
  • 43
  • The definition in the anonymous namespace won't match the declaration in the header file. What are you actually trying to achive? – πάντα ῥεῖ Jun 11 '19 at 17:19
  • what I am trying to achieve is to write 2 definitions (even same) of a function in two different translation units. I read that inline function is a function that may have multiple definition (but they must be the same). – Blood-HaZaRd Jun 11 '19 at 17:21
  • 1
    @Blood-HaZaRd - And that only applies to inline functions. You may not have multiple definitions of non-inline functions. You will get linker errors if you succeed. And if you don't get linker errors, you haven't succeeded. – Omnifarious Jun 11 '19 at 17:22
  • You should better go with a slight extension of the _Pimpl idiom_ to achieve this. – πάντα ῥεῖ Jun 11 '19 at 17:23
  • @πάνταῥεῖ : and why does the the anonymous namespace won't match the declaration in the header file ? In the IDE when I click go to declaration each defined function goes to the header file. – Blood-HaZaRd Jun 11 '19 at 17:23
  • 1
    @Blood-HaZaRd - The anonymous namespace can be thought of as a namespace with a name that is unique to each translation unit. The name of a function includes the namespace in which it was declared. So two functions that are each in an anonymous namespace but in different translate units have different names, even if the function name in the declaration appears to be the same. – Omnifarious Jun 11 '19 at 17:25
  • @πάνταῥεῖ : Got it thank you. – Blood-HaZaRd Jun 11 '19 at 17:26
  • @Blood-HaZaRd Because the anonymous namespace is only present in a particular TU. At the end there would be different mangled symbols for `fct()` coming from the header, and the versions provided in the anonymous namespaces. – πάντα ῥεῖ Jun 11 '19 at 17:26
  • Are you trying to have two different translation units have the same strong symbol of identical code, and then at link time select one preferentially over the other? Or is the code different (which would be an ODR violation), yet still select one preferentially over the other? – Eljay Jun 11 '19 at 17:42

1 Answers1

3

Could I provide same function definition in different TUs

If the function is not declared inline, then no; that would violate the one definition rule.

A inline function with external linkage can be defined in multiple TUs - with additional requirement that the definition must be the same. In fact, the inline declaration would make it mandatory to provide the definition in all TUs that odr-use the function.

and provide 2 definitions in two files each of which is contained into an anonymous namespace:

That doesn't violate standard rules. Those two functions are not the same, nor are they the same as the global ::fct.

But I didn't see how this could be a good examle of using multiple definitions of a function in different TU.

could someone show me a simple example of that (even using inline) thank you

Here you go:

// header.hpp
inline void foo() {}

// a.cpp
#include "header.hpp"

// b.cpp
#include "header.hpp"

Here there are two TU's, each of which contain the definition for the function ::foo, included from the same header. This is allowed because the function is declared inline.


Relevant standard quotes (current draft, irrelevant details redacted by me):

One-definition rule [basic.def.odr]

A ... function, ... shall not be defined where a prior definition is necessarily reachable ([module.reach]); no diagnostic is required if the prior declaration is in another translation unit.

...

Every program shall contain exactly one definition of every non-inline function or variable that is odr-used in that program outside of a discarded statement; no diagnostic required. ... A definition of an inline function or variable shall be reachable in every translation unit in which it is odr-used outside of a discarded statement.

...

There can be more than one definition of a ... inline function with external linkage ([dcl.inline]) ... in a program provided that no prior definition is necessarily reachable ([module.reach]) at the point where a definition appears, and provided the definitions satisfy the following requirements. ... no diagnostic is required unless a prior definition is reachable at a point where a later definition appears. Given such an entity named D defined in more than one translation unit, then

  • Each definition of D shall consist of the same sequence of tokens; and
  • ~ lenghy list of other limitations ~
eerorika
  • 232,697
  • 12
  • 197
  • 326
  • 2
    The one definition rule applies to inline functions as well. The ODR actually has little to do with this. The rule here is that there may be only one definition of a name with external linkage that isn't an inline function. It's why C++17 (or is it 2a?) used the `inline` keyword so you could initialize static variables in the header file (which would appear in multiple TUs). – Omnifarious Jun 11 '19 at 17:26
  • 1
    _@eerorika_ Add a solution how to overcome this problem with a variation of _Pimpl_ and I'll upvote (your already correct) answer. – πάντα ῥεῖ Jun 11 '19 at 17:29
  • @πάνταῥεῖ : it woud be nice if I could see an example of imple of Pimpl as I don't see how we could do thar using pointer to another class !?! sorry if my talk seems dummy, but I may not be as smart as others here :) – Blood-HaZaRd Jun 11 '19 at 17:33
  • 1
    @Blood-HaZaRd It would imply to introduce classes to call these functions in 1st place. – πάντα ῥεῖ Jun 11 '19 at 17:35
  • @πάνταῥεῖ It's unclear to me what problem Pimpl solves. – eerorika Jun 11 '19 at 17:49
  • @Omnifarious As far as I can tell, this has everything to do with ODR. I've added quotes of relevant parts of it. – eerorika Jun 11 '19 at 18:05
  • Pimpl solves the problem that you have to define (not merely forward declare) the types of all the member variables that a class holds by value (rather than pointer or reference). This means a) you need to #include a whole mess of headers to define all the types; b) every time you want to change an implementation detail you force a recompile of all the translation units that use your class. (This latter is a *particular* problem for libraries.) I don't see what pimpl has to do with your answer though. – Martin Bonner supports Monica Jun 11 '19 at 18:19
  • 1
    @MartinBonner Yeah, I meant, it's unclear what problem in context of this question (and answer) it solves :) That is: I don't see a problem stated in the question that can be solved using Pimpl. – eerorika Jun 11 '19 at 18:21
  • @eerorika - Oh, you're right. I thought the ODR was only about the fact that all definitions of a function must be identical in every translation unit. But, in fact, it seems there isn't a specific term for this and the ODR is all about external linkage and reachable definitions with inline functions being presented as being a very specific and limited semi-exception. – Omnifarious Jun 11 '19 at 19:11