简体   繁体   中英

How to initialize global const variables in a namespace with values from a function?

I'm reading in a bunch of 'settings' for an application from an XML file and I want those settings to reside in a namespace for all my functions to be able to access. I have succesfully made this work by declaring the namespace variables in the header as 'extern int test;' and then initializing them in the source file 'int test{0};'. Then in the source file there is a function that reads the XML and assigns the the value to the namespace variable and everything is hunky dory.

Problem is I realize I'm creating ~100 read/writeable global variables when they only need to be constant. So I'm trying to change my code now that they are constant and I don't see how it's possible. Here's what I tried:

//settings.hpp
#pragma once
//header guard

namespace settings {
    extern const int ktest;
}

//settings.cpp
void ReadXML() {
    int testvalue{1}; //1 is default values

    //here would be some code that gets value form XML and assigns it to testvalue

    namespace settings {
        const int ktest{testvalue};
    }
}

Now the problem is I cannot put the namespace values inside the function. So if I move them outside the function ReadXML, I have to move the temporary variables as well, but even so it doesn't matter because I need the namespace variables initialized only after the function is executed. Is what I am trying to do even possible?

declare a function prototype in header file then your namespace and make the extern constant be initialized depending on its return. then define your function in main:

//header.hpp
#pragma once

int RetValue(); // prototype

namespace A{
    extern const int value(RetValue());
}


//source.cpp

int RetValue(){return 7;} // defining retValue

int main()
{
    cout << A::value << endl; // output: 7 
}

OK, I'm not sure if this was what raindrop was getting at, but it inspired me to find this solution. Here's my structure:

//xmlreader.hpp
#pragma once
//header guard

int ReadXML();

namespace settings {
    extern const int kreadsucces;   //Has to be first, is result of read function
    extern const int ktest;
}

//xmlreader.cpp
#include "xmlreader.hpp"
static int test {0};            //Default in case of exception in read function

int ReadXML() {
    //xml read code here, assign new 'test' value if successful
    test = 2;
    return 1;
}

namespace settings {
    const int kreadsucces{ReadXML()};   //ReadXML is executed before main now!
    const int ktest{test};
}

//main.cpp
#include "xmlreader.hpp"
// if (ReadXML() > 0) {}                //Was old code, now called at initialization
if (settings::kreadsuccess > 0) {
    std::cout << "XML read succesful" << std::endl;
} else {
    std::cout << "XML read failed, using defaults" << std::endl;
}
std::cout << settings::ktest << std::endl; //Prints 2

What I did was add the 'settings::readsuccess' variable and initialize it with my function instead of calling it at the start of my main. Now this function actually runs immediately at program launch before even main starts and assigns all those place holder variables, so when the other variables get initialized the functions already been ran.

Now I admit, what I did seems a bit of a shortcut, but it works and now I've got a namespace full of 100 global const variables initialized at runtime that are accessible everywhere else in my program by including the header file. Is this legit, or better put, is it a better practice than just having 100 mutable global variables?

In order to set a constant global variable, you need to set it when it is defined. So do this:

const int ktest = getValueofKtest();

Also, setting up one hundred variables is a maintenance nightmare. Use a settings class.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM