Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to pass entire collection(char**) of command line arguments as read-only in c++?

Suppose I have a program like this:

#include <iostream>
#include <string>
#include <vector>

// Takes values and outputs a string vector.
std::vector<std::string> foo(const int argc, char* args[]) {
    std::vector<std::string> strings;
    for (int i = 0; i < argc; i++)
        strings.push_back(args[i]);
    return strings;
}

int main(int argc, char *args[]) {

    std::vector<std::string> strings = foo(argc, args);

    for (unsigned int i = 0; i < strings.size(); i++)
        std::cout << strings[i] << std::endl;

    return 0;
}

Where the takeaway is that I'm trying pass the main() function's char** argument to another function or class. (I understand there are better ways to achieve what the above program does, my question is about passing char** arguments as read-only).

Questions:

  1. I've found that I can't make the second foo() argument const like the first. Why is this? A char** can't be converted to a const char**?
  2. I want to pass in this argument as "read-only". I'm not sure how to go about this, if it were say a string I'd pass it in via const reference, but I'm not sure how to go about this with pointers?
like image 850
Jaymaican Avatar asked Feb 11 '19 11:02

Jaymaican


1 Answers

I've found that I can't make the second foo() argument const like the first. Why is this? A char** can't be converted to a const char**?

If it were allowed, you'd be likely to break const correctness. Consider this

char const *a = "literl";
char *b = nullptr;
char const **c = &b; // This is not allowed in C++. Like your code.
*c = a; // The qualifications match, but now it's b that points at a literal.
*b = 'L'; // Modifying a string literal! Oops!

So there is a good reason to disallow it as written. But that doesn't mean you can't do what you want at all. Qualification conversions are possible so long as they are stricter. Well that's the gist of it anyway.

I want to pass in this argument as "read-only". I'm not sure how to go about this, if it were say a string I'd pass it in via const reference, but I'm not sure how to go about this with pointers?

Pass a pointer to a const pointer to a const char. Better write it in code to explain:

                                                         // The const here
std::vector<std::string> foo(int const argc, char const* const args[]) {
    std::vector<std::string> strings;
    for (int i = 0; i < argc; i++)
        strings.push_back(args[i]);
    return strings;
}

Why is this allowed? Because if we equate it to the bad example I started with, c can no longer be used to assign to b, and so we cannot get into an erroneous state.

like image 174
StoryTeller - Unslander Monica Avatar answered Sep 20 '22 00:09

StoryTeller - Unslander Monica