Search code examples
c++functioncommand-line-argumentsinitializer-list

Are there any problems in using a Static Member Function to initialize a Constant Member Variable in an Initializer List?


I wish to have a class in my program that directly takes the Command Line arguments from the main method. I want some of this information to be Constant to the Class, but also dependant upon the Command Line arguments that were entered.

I have read the detailed answer here: C++ defining a constant member variable inside class constructor , however I am still a little confused...

main.cpp:

#include "Launcher.h"

int main(int argc, char *argv[]) {
    Launcher launcher(argc, argv);

    // do other stuff with launcher

    return 0;
}

Launcher.h:

#ifndef LAUNCHER_H
#define LAUNCHER_H

#include <string>
#include <vector>

class Launcher {
public:
    Launcher(int, char *[]);

private:
    const int argumentCount;
    const std::vector<std::string> arguments;

    static const std::vector<std::string> INIT_arguments(int, char *[]);
};

#endif

Launcher.cpp

#include "Launcher.h"

Launcher::Launcher(int inputCount, char *inputArguments[]) :
    argumentCount(inputCount),
    arguments(INIT_arguments(inputCount, inputArguments))
{}

Launcher::INIT_arguments(int inputCount, char *inputArguments[]) {
    std::vector<std::string> argumentVector;
    for (int i = 0; i < inputCount; i++) {
        std::string currentArgument = inputArguments[i];
        argumentVector.push_back(currentArgument);
    }
    return argumentVector;
}

(I understand that in this example there may be alternative methods to achieve the same results by not using an initializer lists. In other cases I've used complex functions to determine the const variable's value but chose this simple example to demonstrate the concept.)

My questions are:

  1. Are there any problems with initializing a const member variable by using a static function(In the example above)?
  2. Does anything change / are there any more problems if the function used to initialize the const variable is non-static?
  3. Is there any difference between defining the function in the header file alongside its declaration versus how its been declared in the header file then defined in the source file? Are there any differences if it's static/non-static?
  4. Unrelated to the general question but... Is there an easy way to pass the char *[] variable by reference or perhaps a more efficient way?

Solution

  • Are there any problems with initializing a const member variable by using a static function(In the example above)?

    No. One could argue that such a local helper function that has little to do with your actual class could instead be outsourced into a helper/utility entity, maybe a free function (template) in an anonymous namespace or somewhere else (to make it testable).

    Does anything change / are there any more problems if the function used to initialize the const variable is non-static?

    Making it static ensures that the member function has nothing to do with any of the instances' state (same for free functions, obviously). I would definitely keep it that way for functions that are used to initialize state.

    Is there any difference between defining the function in the header file alongside its declaration versus how its been declared in the header file then defined in the source file?

    No. If you would make it a free function though, you need to take care of possible ODR violations, and at least mark it as inline.

    Is there an easy way to pass the char *[] variable by reference or perhaps a more efficient way?

    There is a more efficient way, i.e., not using the function at all and rely on the std::vector constructor (overload #4) that takes two iterators as arguments. Pointers to the same raw array are fine here, so you can just do:

    Launcher::Launcher(int inputCount, char *inputArguments[]) :
       argumentCount(inputCount),
       arguments(inputArguments, inputArguments + inputCount) {}
    

    Note also that Launcher doesn't seem to intend modifying the command line arguments. In this case, you don't have to copy the strings at all. Use a std::string_view instead (if C++17 is available) or just leave it as const char* (one nice thing about command line arguments is that you don't have to think about their lifetime).