-1

My goal is that when I call myFunction from within main, I do not have to pass the SIZE constant. The function within myFunction.cpp should then run and simply output the contents of the array.

I've read some notes on external linkage but I feel like I don't understand it well enough to apply anything in this case. Ideally main.cpp shouldn't be changed much other than giving the namespace including SIZE a name if absolutely necessary.

main.cpp

#include <iostream>
#include "myFunction.hpp"

namespace
{
    extern const int SIZE = 10;
}

void myFunction(char []);

int main()
{
    char myArray[SIZE] = "123456789";

    myFunction(myArray);
}

myFunction.h

#ifndef MYFUNCTION_H_INCLUDED
#define MYFUNCTION_H_INCLUDED

namespace
{
    extern const int SIZE;
}

#endif // MYFUNCTION_H_INCLUDED

myFunction.cpp

#include <iostream>

void myFunction(char myArray[])
{
    for(int i = 0; i < SIZE; ++i)
    {
        std::cout << myArray[i] << " ";
    }
}

With what I have so far I still get the error that SIZE was not declared in that scope (myFunction.cpp).

Question: What do I have to do to make this example work? If possible, I'd also love an explanantion of why one would handle sharing SIZE this way.

Cartino
  • 41
  • 1
  • 7
  • 1
    Anonymous namespaces are always, by definition, local/private to the translation unit, which means that stuff declared in an anonymous namespace is ***only*** accessible in the same source module. What exactly do you intend to accomplish by declaring `extern` linkage in the anonymous namespace, and how exactly did you expect that to work? – Sam Varshavchik Mar 09 '19 at 01:44
  • main.cpp was provided pre-built as a driver. As I stated my goal is for the constant SIZE located within that anonymous namespace to be available for use in myFunction.cpp without actually passing it. – Cartino Mar 09 '19 at 01:46
  • I don't know what "main.cpp was provided pre-built as a driver" means. Again: an anonymous namespace is, by definition, anonymous. It can only be used and referenced in the ***same*** translation unit. Objects declared in a translation unit's anonymous namespace are not available from any other translation unit. Your second .cpp file simply declares a `SIZE` in its own, individual, anonymous namespace, that itself is not accessible from any other translation unit. Your stated goal is, unfortunately, not possible in C++. C++ does not work this way. – Sam Varshavchik Mar 09 '19 at 01:49
  • I mean main.cpp was provided to me as part of an exercise -- "Notice that you are passing myArray to the function. Notice too that we have the global namespace below. The number of array positions used is found in a constant aptly named SIZE. What the goal of this is – we will not pass SIZE as a parameter. Instead, we will try to share this SIZE constant by using external linkage as it is defined below (in an unnamed namespace). Try to get this to work. You may give the unnamed namespace holding SIZE a name if that helps" -- The instructions imply it's possible, no? – Cartino Mar 09 '19 at 01:54
  • Either these instructions are incomplete, or wrong, or they do not require the usage of more than one translation unit. – Sam Varshavchik Mar 09 '19 at 01:57
  • So what would you suggest to achieve the aforementioned goal? myFunction.h and myFunction.cpp are mine to program, and as I said I can name the namespace containing the constant in main.cpp if necessary. – Cartino Mar 09 '19 at 02:01
  • Name it and you can export it, but as Sam's pointed out if you don't name it, everything in it it bound to that one file. – user4581301 Mar 09 '19 at 02:06
  • Unrelated: `SIZE` is 10, but `myArray` only has 9 printable elements and the terminating null. When you get this working your output may look a bit funny as a result. – user4581301 Mar 09 '19 at 02:09

1 Answers1

2

An unnamed namespace tells the compiler that nothing inside is to be shared with another translation unit. (That is, everything inside has internal linkage.) As long as SIZE is in an unnamed namespace, it cannot have external linkage, so it cannot be seen by myFunction().

If possible, I'd also love an explanantion of why one would handle sharing SIZE this way.

Since you are working with a toy exercise, my guess is that one would handle sharing SIZE this way to better understand internal and external linkage. It's an exercise, not a real-world example.

For a more realistic example, maybe a version string would be both simple and good? Your app might have a version (e.g. "1.69.8109") that it displays at various points. This version could be declared as a const string that is used by several source files. It would go into a (named) namespace to avoid name conflicts. It could be defined in a source file rather than a header file to limit the amount of re-compilation needed when the version changes. (Only the source with the definition would need to be recompiled, not every source that uses the version string.) This might be a reasonable benefit, especially if the version number changes reasonably often, not necessarily just when a new release is being prepared.

(From the comments): "Try to get this to work. You may give the unnamed namespace holding SIZE a name if that helps"

It's funny how often instructions for an exercise will tell you what to do. (Heh, "if".)

JaMiT
  • 14,422
  • 4
  • 15
  • 31
  • 1
    By what you're saying I suppose that we are not allowed to pass a pointer or reference to a variable contained in an unnamed namespace to another function of another translation unit. Am I right or wrong? – KeyC0de Jul 26 '22 at 11:11
  • 2
    @KeyC0de Note the phrasing: "unnamed namespace **tells the compiler** that nothing inside is to be shared with another translation unit" (emphasis added). The compiler is not to share the contents of an unnamed namespace. You, as the programmer, are not bound by this restriction. *(The compiler similarly will not share a function's local variables with other functions, but nothing stops the programmer from passing them as parameters. Your option, not the compiler's.)* – JaMiT Jul 28 '22 at 06:31