When to use namespace {} and when :: in multifile projects

Hello! :)

I'm a bit at sea when it comes to both namespaces and externs.
If I do this in file.cpp
1
2
3
4
namespace ns {
	enum loc { ... }; // or class loc { ... } fails too
	loc lang = some_instantialisation;
}


Now I see four possibilities of announcing the lang variable in file.h. Those logical possibilities are:

1
2
3
4
5
6
7
extern ns::loc ns::lang; // 1 approach
extern ns::loc lang; // 2 approach
extern loc ns::lang; // 3 approach

namespace ns { // 4 approach
	extern loc lang;
}


Which one is the correct one? It seems like each and every one of those, which I tested, fail at compile time (for example: loc is not a member of ns or that there is a semicolon missing before *)

P.S As a side note - there was a very insightful article on this site that basically said "forward declare if the thing you want to use is of type* or type&". However, when I wanted to forward declare

extern enum_type& var;

the compiler complains. Do I have to include the entire header for such occurences? The compiler doesn't need to know it's size because the var itself is just a memory address :-|
Last edited on
define the class in the header file.

> fail at compile time
bother yourself to copy-paste the error message.

> that basically said "forward declare if the thing you want to use is of type* or type&
forward declare the class.
the compiler needs to know that `enum_type' is a class
Sorry for not posting the errors :) I thought a more general way of describing the problem would help not to localise the issue for future users, but anyway.

globals.h (includes classes.h)
1
2
3
4
extern int settings[];
namespace lang {
	extern localisation* current_lang; // at this line
}


current_lang is defined in globals.cpp lang::localisation* current_lang = NULL;

classes.h
1
2
3
4
5
6
namespace lang {
	class localisation {
	public:
		// .... //
	}
}


Error:
error C2143: syntax error: missing ';' before '*'
Last edited on
About your first post:
Tobruk wrote:
If I do this in file.cpp
1
2
3
4
namespace ns {
	enum loc { ... }; // or class loc { ... } fails too
	loc lang = some_instantialisation;
}

Now I see four possibilities of announcing the lang variable in file.h.

The header file is the right place for declaring what you want to be seen in source files, not the other way round.

Tobruk34.h:
1
2
3
4
5
6
7
8
#ifndef TOBRUK34_h
#define TOBRUK34_h

namespace ns {
    enum loc { TOBRUK_1, TOBRUK_2, TOBRUK_3 };
}

#endif // TOBRUK34_h 


Tobruk3.cpp:
1
2
3
4
5
#include "Tobruk34.h"

namespace ns {
    loc lang = TOBRUK_3;
}


Tobruk4.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
#include <iostream>
#include "Tobruk34.h"

namespace ns {
    extern loc lang;
}

int main()
{
    std::cout << "ns::lang == " << ns::lang << '\n';
    return 0;
}


Output:
ns::lang == 2


But it seems ne555 got the main point from the very beginning:
ne555 wrote:
forward declare the class.

because in your second post:
Tobruk wrote:
globals.h (includes classes.h)
1
2
3
4
extern int settings[];
namespace lang {
	extern localisation* current_lang; // at this line
}
you are likely to be missing a forward declaration of localisation before the mentioned line.
class localisation;
Last edited on
Okay, I did a cleanup of my header repository and divided my declarations into smaller, more strategic headers (without any circular dependecies).
I almost got everything right, except for 3 unresolved external symbols :(

Error

LNK2001 unresolved external symbol "class lang::localisation lang::current_lang LNK2001 unresolved external symbol "class lang::localisation lang::l_english LNK2001 unresolved external symbol "class lang::localisation lang::l_polish

This is my include chain for word.obj (at least that's how it is called by the compiler) which was the first to be linked by the Linker I guess, and failed.

word.cpp --> lang_global.h --> lang_class.h --> lang_enum.h --> RETURNS to words.cpp

lang_global.h

1
2
3
4
5
namespace lang {
extern localisation* current_lang;
extern localisation l_english;
extern localisation l_polish;
}

P.S The externs here are defined in another .cpp file that is connected to this header.
globals.cpp

1
2
lang::localisation* current_lang = NULL;
lang::localisation l_english, l_polish;


lang_class.h

1
2
3
namespace lang {
class localisation {...}
}


lang_enum.h

some irrelevant enums

So, as evident in the include chain, everything is forward declared before it is used. I don't know what the Linker complains about. Help, please :)
Last edited on
http://www.cplusplus.com/forum/general/113904/
show your build command.


> lang_enum.h --> RETURNS to words.cpp
¿? ¿what do you mean it returns?
Hi, Tobruk.
As a matter of fact, these files
main.cpp:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <iostream>
#include <limits>

void waitForEnter();

int main()
{
    waitForEnter();
    return 0;   
}

void waitForEnter()
{
    std::cout << "\nPress ENTER to continue...\n";
    std::cin.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
}


globals.cpp:
1
2
3
4
5
#include "lang_global.h"

lang::localisation* current_lang = nullptr;
lang::localisation l_english, 
                   l_polish;


lang_enum.h:
1
2
3
4
5
6
#ifndef LANG_ENUM_H
#define LANG_ENUM_H

// irrelevant but top secret

#endif // LANG_ENUM_H 


lang_classes.h:
1
2
3
4
5
6
7
8
9
10
#ifndef LANG_CLASS_H
#define LANG_CLASS_H

#include "lang_enum.h"

namespace lang {
    class localisation {};
}

#endif // LANG_CLASS_H 


lang_global.h:
1
2
3
4
5
6
7
8
9
10
11
12
#ifndef LANG_GLOBAL_H
#define LANG_GLOBAL_H

#include "lang_class.h"

namespace lang {
    extern localisation* current_lang;
    extern localisation l_english;
    extern localisation l_polish;
}

#endif // LANG_GLOBAL_H 


compile 0 errors 0 warnings with the following command:
g++ -std=gnu++17 -Wall -Wextra -pedantic-errors -pipe -O3 main.cpp globals.cpp -o main.exe

So, if you're still getting errors, they could be in parts of code you didn't show us.
Topic archived. No new replies allowed.