Again Inclusion question

Started by
29 comments, last by MarcusAseth 6 years, 6 months ago

Hi guys, I would like to have the header below:

Paths.h


#pragma once
#include <string>

namespace Paths {
	
	namespace Images {
		static std::string CHECKER = "Graphics/Checker.png";
	}

	namespace Fonts {
		static std::string BUBBLEBATH = "Fonts/BUBBLEBATH.ttf";
	}

}

Included all around the place so that I can do stuff like Paths::Images::CHECKER to easily load the proper file or to request it again by passing that to a map as a key.

Though this I believe create a copy of the static string for every compilation unit, am I correct? Meaning I include it in 10 cpp and get 10 copies of each string.  How would I do this the proper way?

Advertisement

Change the "static" with "const"? Or don't use static and const if you still want to be able to change these strings.

If static is used outside of a function or class, it ensures the variable/function can only be used by code in that specific file (translation unit to be precise), and nowhere else. const variables are prevented from changing.

Furthermore, use lower case characters for globals. Most programmers use full upper case for macros. You coud use something like g_checker and g_bubblebath to explicitly indicate these variables are global (though scoped to some namespace). Alternatively, you can consider to use macros for these file names if you intend to add hundreds of them to your code. This will reduce your memory usage.

🧙

@matt77hias that doesn't solve the problem.

Anyone knows how to avoid multiples copies being created for every single variable?  :\ 

The exact answer depends on compiler and options you use. Duplicates can be eliminated by compiler/linker, especially if LTO (Link Time Optimization) can be used.

See: "Overhead of static constants when included into many translation units?"

Apparently C++17 introduces inline variables.


inline const std::string my_string = "MyString";

 

🧙

Ok I think I've figured it out myself, extern to the rescue :D

Paths.h


#pragma once
#include <string>

namespace Paths {
	
	namespace Images {
		extern std::string CHECKER;
	}

	namespace Fonts {
		extern std::string BUBBLEBATH;
	}

}

Paths.cpp


#include "Paths.h"

std::string Paths::Images::CHECKER = "Graphics/Checker.png";
std::string Paths::Fonts::BUBBLEBATH = "Fonts/BUBBLEBATH.ttf";

 


header file

namespace Paths {
	
	namespace Images {
		extern std::string CHECKER;
	}

	namespace Fonts {
		extern std::string BUBBLEBATH;
	}

}

source file 
#include <Paths.h>

namespace Paths {
	
	namespace Images {
		std::string CHECKER = "Graphics/Checker.png";
	}

	namespace Fonts {
		std::string BUBBLEBATH = "Fonts/BUBBLEBATH.ttf";
	}

}

 

@AxeGuywithanAxe I've beaten you by few seconds :D But thanks :)

Also, any major differences in the way I did it above and in the way you did it? Or is a style choice? 

1 minute ago, MarcusAseth said:

@AxeGuywithanAxe I've beaten you by few seconds  But thanks

Also, any major differences in the way I did it above and in the way you did it? Or is a style choice? 

Yeah, i saw that.. haha... not a difference, just style choice and laziness (I just copied and pasted your original comment and added extern and removed static , etc)

I've learned about extern today and suddenly it became my favourite C++ keyword I think :D

 

44 minutes ago, MarcusAseth said:

I've learned about extern today and suddenly it became my favourite C++ keyword I think

 

Until you discover the static initialization order fiasco.

Generally I create free functions to provide well-known constant values that cannot just be constexprs.

This topic is closed to new replies.

Advertisement