0

I'm trying to abstract away some GLFW input code by using a global variable state to keep track of key presses.

I thought using namespaces would be nice, so I thought doing something like:

namespace InputState { namespace KeyPressed { static bool left = false; static bool right = false; static bool down = false; static bool up = false; }; }; 

and then accessing these variables like

if (glfwGetKey(window, GLFW_KEY_LEFT) == GLFW_PRESS) { InputState::KeyPressed::left = true; } else { InputState::KeyPressed::left = false; } 

and

if (InputState::KeyPressed::left) { body->velocity.x -= 0.25f; } 

would be really easy and visually/architecturally appealing, but as I've found out, creating static variables in namespaces brings some weird behavior that make this not work as intended.

I've tried using extern, but that gave me linker errors stating that there was a redefinition of the variables. I've triple checked that I have my header guards in place.

Is there some way I can get this working where I truly have a global variable within a namespace or is this just not possible/not intended behavior for namespaces?

5
  • You do it the same way as without namespaces. I suspect you made some mistake with extern (such as keeping the initialization of the variables in the header) that made you believe that namespaces are relevant to the issue. (Header guards only protect against multiple inclusions in a translation unit. If you include a definition in multiple translation units you still get multiple definitions.) Commented Nov 25, 2021 at 10:34
  • 1
    In general, global variables are considered as bad. They rely on being changed in a function where this isn't obvious from its declaration that it does modify something with outside storage. Thus, such things become hard to understand and maintain as soon as the S/W grows. A replacement could be to put the resp. variables in a struct which is passed by reference (or const reference) where ever it's modified (or evaluated). A side effect would be that your extern issue would vanish. Commented Nov 25, 2021 at 10:35
  • @Scheff'sCat I understand what you mean. This is in the context of a game engine and so I'm trying to figure out a way to maintain input state without just calling directly into the keyboard state that GLFW provides. The interface is quite ugly and my goal is to essentially abstract away everything GLFW related within my engine. Is there a better way without the use of structs as you mentioned? I feel like passing a struct around for keyboard state would become cumbersome and unwieldy quickly. Commented Nov 25, 2021 at 10:49
  • 2
    I feel like passing a struct around for keyboard state would become cumbersome and unwieldy quickly. With a struct 1.) You don't need any global variable. A local variable in main() has sufficient life-time as well. 2.) The respective function to read out the keyboard state has to get a reference to that variable. 3.) Where you want to check the current keyboard state, you have to pass a const reference to that struct. Commented Nov 25, 2021 at 10:53
  • 3
    -> Every where where functions handle the keyboard state, they will appear as argument in the function call. You might think that's tedious - I think that's easy to understand. (No surprises.) Btw. it's not only for other readers. I remember that I often enough didn't know anymore what I did in the code I wrote a half year ago (but this might be a matter of age). Finally, it's your code and you are free to do whatever you like most. (One of the advantages to write S/W I most appreciate.) It's just that I felt encouraged to give you another opinion... ;-) Commented Nov 25, 2021 at 10:56

1 Answer 1

2

Is there some way I can get this working where I truly have a global variable within a namespace or is this just not possible/not intended behavior for namespaces?

If you want to use these variables in other source file then you can do so using extern as follows:

myheader.h

#ifndef MYHEADER_H #define MYHEADER_H namespace InputState { namespace KeyPressed { extern bool left, right, down, up; }; }; #endif 

mysource.cpp

#include "myheader.h" namespace InputState { namespace KeyPressed { bool left = false; bool right = false; bool down = false; bool up = false; } } 

main.cpp

#include "myheader.h" #include <iostream> int main() { std::cout<<InputState::KeyPressed::left<<std::endl; InputState::KeyPressed::left = true; std::cout<<InputState::KeyPressed::left<<std::endl; } 

Just like i have used the variable InputState::KeyPressed::left in main.cpp you can now use it in your own file and it will work.

The above program works as can be seen here.

Sign up to request clarification or add additional context in comments.

10 Comments

This works but it really is terrible code.
@KonradRudolph The question is about solving the issue that OP is facing.Nobody, literally nobody said that this is the best code ever or i have to write it in best way possible.It may happen that the OP is unaware of the fact global variables should not be used,in which case your comment might be useful to him.Again,i focus on solving the current problem.That is,i post the answer that answers(or at least tries to answer)what OP asked. More importantly,this answer can at least tell the OP about how to use the extern keyword in this scenario.Ofcourse the answer also solves his/her issue.
@KonradRudolph This is in the context of a game engine. I'm trying to create an interface to maintain input state. The idea was to have components that need input context to include the header, otherwise the input state remains untouched. The only time the values of the booleans get changed would be in a different header that directly listens for keyboard input via GLFW's keyboard input interface. What can I do that basically allows you to directly access grouped variables without the use of a class/instantiation?
@AnoopRana There’s a place for answers that solve a narrow issue (hence no downvote from me) but it’s vastly more helpful to address the actual, underlying problem and fix that, or at least make OP aware of it. “Helping” people be more effective at writing bad code isn’t helping them at all, and is counter-productive in the long run. Instead, Stack Overflow should teach them write better code.
@AnoopRana “The question does not ask about better alternatives to global variables.” — My point is that this is utterly irrelevant. People often ask for bad solutions because they simply don’t know any better. As already mentioned, it is our task to teach them, not to help them write bad code. When answering questions on Stack Overflow, your task is to be a good teacher, not just an answering machine. — Also, you say that OP is “aware of the consequences”. Sure, but OP seems unaware that using this bad solution is unnecessary, and that better solutions exist.
|

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.