6

I have a single global helper function which is used by a bunch of macros in a header file. The intention is to allow the macros to be usable by simply #include'ing the single header (in other words, I'd like to keep the function definition in the header and avoid putting it in a separate compilation unit). However, this causes problems when an application #include's this file in more than one compilation unit, as the duplicate symbols problem arises.

The helper function has enough characteristics in which it shouldn't be declared inline.

I was messing around and found that using unnamed namespaces solves the problem of duplicate symbols, i.e.:

namespace
{
    void foo(...)
    {
    }
};

#define HELPER_A foo(1, ...);
#define HELPER_B foo(2, ...);
...

Is there any downside to this approach? Are there better alternatives?

jwalk
  • 1,120
  • 11
  • 27
  • did not get what is the problem with putting the definition in a .cpp file. – Terenty Rezman May 31 '13 at 07:18
  • Do you really want your code to duplicate in different compilation units? Why not using #pragma once? – akalenuk May 31 '13 at 07:18
  • 1
    You mention that it shouldn't be declared "inline", but do you actually want a discrete implementation of it for every compilation unit was included into - that seems wasteful. Why not just put it in its own compilation unit and simply declare it "extern" in the header file? – kfsone May 31 '13 at 07:31
  • `I'd like to keep the function definition in the header and avoid putting it in a separate compilation unit` Why? – Lightness Races in Orbit May 31 '13 at 07:31
  • 1
    `The helper function has enough characteristics in which it shouldn't be declared inline` I doubt it. If the compiler doesn't think the function should be inlined then it won't be, but the `inline` keyword will give the function the correct linkage to avoid the multiple definition error. – Lightness Races in Orbit May 31 '13 at 07:32
  • Unnamed namespaces should not be used in header files. See: http://stackoverflow.com/q/357564/143504 – Julien-L May 31 '13 at 07:38
  • @Julien-L If the header explicitly does not have an associated compilation unit, why exactly is it a bad thing? – jwalk May 31 '13 at 12:21
  • The interface is to be used by multiple applications, and I don't see a point in the overhead of a whole DLL just because of one function that I couldn't find a way to somehow inline. – jwalk May 31 '13 at 12:24
  • @LightnessRacesinOrbit As-per http://stackoverflow.com/questions/1932311/when-to-use-inline-function-and-when-not-to-use-it, the function is not small (around 25 lines) and IO-bound – jwalk May 31 '13 at 12:29
  • @jwalk: Meh, that answer isn't completely spot-on. You wouldn't use `inline` here expecting to actually get function inlining, no, but then that's not the purpose either. The purpose is simply to bypass ODR. _That said_, see my first comment... it'd be best to avoid this requirement entirely. – Lightness Races in Orbit May 31 '13 at 13:27
  • @LightnessRacesinOrbit I guess that's reasonable, though I'd still consider it much larger overhead to require the apps to link to yet another library just to follow what is considered to be "best practice", when this overhead could easily be avoided and there are no concrete problems with the alternative approaches of inlining and unnamed namespaces. – jwalk May 31 '13 at 14:55
  • @jwalk: Um I never advocated using any libraries. The problem with your approach is (a) code bloat, (b) cache trashing, (c) it just makes very little sense. – Lightness Races in Orbit May 31 '13 at 14:59
  • @LightnessRacesinOrbit See my comment above. This code is being used by multiple applications. – jwalk May 31 '13 at 14:59
  • @jwalk: Doesn't stop you from sharing a source code file between them. How about a nice `.a`? That is the proper way to do it and your aversion to "best practice" is silly -- best practices aren't arbitrary. – Lightness Races in Orbit May 31 '13 at 15:12
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/30995/discussion-between-jwalk-and-lightness-races-in-orbit) – jwalk May 31 '13 at 15:18
  • @jwalk: No thanks - it's not for my benefit. :) – Lightness Races in Orbit May 31 '13 at 15:57

1 Answers1

3

You are only allowed one function definition in your project unless its marked as inline. You may have as many function declarations as you wish (aka function prototypes).

Move your function definition to a .cpp file and just leave the declaration in the header file

void foo(...); // no function body makes this a declaration only

or you could mark it inline:

inline void foo(...) { /* ... */ } 

inline functions should be small and computationally fast as a general rule.

RobbieE
  • 4,280
  • 3
  • 22
  • 36
  • 5
    While your answer is factually accurate, the OP already mentioned both of these approaches and you failed to address _why_ the OP should now consider them when he has chosen not to previously. – Lightness Races in Orbit May 31 '13 at 07:33