8 Comments

How is a symbol in anonymous namespace different than a symbol marked as static?

Expand full comment
author

Can't have a static struct.

Expand full comment
Jun 25·edited Jun 25

Isn't it enough to define the struct in .cc file instead of a header to make it invisible for other compilation units?

For example the following seems to work just fine:

> cat test2.h

#pragma once

int bar(int);

> cat test2.cc

#include "test2.h"

struct test {

int x;

};

int bar(int x) {

test t;

t.x = x;

return t.x;

}

> cat test.cc

#include "test2.h"

struct test {

int a;

int b;

};

int main() {

test t;

t.a = bar(0);

t.b = 1;

return 0;

}

> g++ -c -I. test2.cc

> g++ -c -I. test.cc

> g++ -I. test.o test2.o

> ./a.out

Expand full comment

If I change test.cc to:

> cat test.cc

#include "test2.h"

struct test2 {

int a;

int b;

};

int main() {

test t;

t.x = bar(0);

return 0;

}

Then the compilation fails with:

> g++ -c -I. test.cc

test.cc:9:5: error: unknown type name 'test'; did you mean 'test2'?

test t;

^~~~

test2

test.cc:3:8: note: 'test2' declared here

struct test2 {

^

test.cc:10:7: error: no member named 'x' in 'test2'

t.x = bar(0);

~ ^

2 errors generated.

Expand full comment
author

Well, yes, but sadly no.

In C++ a struct (class, its members, etc...) has external linkage, meaning that if you have a struct of the same name with a different definition in another unit, that is breaking One Definition Rule.

Expand full comment

What does it mean in practise? Why is my first example compiling and working?

Expand full comment

I guess that answers my qustion:

```

a class, which is a type, does not have a linkage, instead it is referring to the linkage of the symbols defined in the class scope (but not the linkage of an object made using the class). This includes static members and methods and non-static methods, but not non-static members as they are only part of the class type definition and do not additionally declare / define actual symbols.

```

Adding a member function like this:

> cat test.cc

#include "test2.h"

struct test {

int a;

int b;

int foo();

};

int test::foo() {

return 1;

}

int main() {

test t;

t.a = bar(0);

t.b = t.foo();

return 0;

}

> cat test2.cc

#include "test2.h"

struct test {

int x;

int foo();

};

int test::foo() {

return 2;

}

int bar(int x) {

test t;

t.x = x;

return t.foo();

}

Causes a compilation/linking error:

> g++ -I. test.o test2.o

duplicate symbol '__ZN4test3fooEv' in:

test.o

test2.o

ld: 1 duplicate symbols

clang: error: linker command failed with exit code 1 (use -v to see invocation)

Expand full comment