Search code examples
c++constantsexternlinkage

C++ : forward declaring const with internal linkage


I want to forward declare a const variable without giving it external linkage. It seems to me, however, that this is impossible because the extern keyword simultaneously means "this has external linkage" and "this is a variable declaration, not a definition", and I can't get one without the other:

//// main.cpp: ////

extern const char table[256];    // forward declaration. External linkage.
// const char table[256];        // Error: table requires an initializer
// static const char table[256]; // Same error

// foo uses table so I need it forward declared:
char foo()
{
    // uses table
}

const char table[256] = {...}; // Actual definition

Is my understanding correct? Are there any workarounds?


Solution

  • First of all, a forward declaration is defined only for types. You can type

    class X;
    

    and then use X * for example.

    What you are trying to achieve here, is declare symbol before actual usage. The only way I know to do this is via extern keyword.

    But if want to make symbol linkage internal, anonymous namespace can help

    namespace {
    extern const char table[256]; // symbol declaration. Internal linkage.
    }
    
    char foo() {
        // use table
    }
    namespace {
    const char table[256] = {...}; // symbol definition. Internal linkage.
    }
    

    Here is a test you can do

    $ cat test.cc
    extern const char moo[4];
    char foo() { return moo[2]; }
    const char moo[4] = {0};
    $ g++  -c test.cc -o test.o -O3 && g++ test.o -shared -o test.so && nm -gD test.so | grep moo
    00000000000005ad R moo
    $
    
    $ cat test.cc
    namespace {
        extern const char moo[4];
    }
    char foo() { return moo[2]; }
    namespace {
        const char moo[4] = {0};
    }
    $ g++  -c test.cc -o test.o -O3 && g++ test.o -shared -o test.so && nm -gD test.so | grep moo
    $