4

I have a class which takes the main command line arguments (eg, -B, -a, etc) and does something with them, but also i would like to be able to instantiate that function without passing the command line arguments, so for example:

constructor:

myClass(int argc, const char **argv){
    <initialise class with flags from argv>
}

myClass() : myClass(2, "-B") {}
}

Here i am trying to instantiate myClass with the flag "-B", but it keeps giving me the error:

no known conversion for argument 3 from ‘const char [3]’ to ‘const char**’

so i was wondering what i need to do to pass a value in as const char**?

guskenny83
  • 1,321
  • 14
  • 27
  • 3
    This is **not the real code**. Please post real code. For now, voting to close as lacking example. – Cheers and hth. - Alf Aug 09 '16 at 06:48
  • Note 1: If you want to pass the `main` arguments, then the type `const char **argv` won't do. There's no implicit conversion from `char**` to `char const**`. – Cheers and hth. - Alf Aug 09 '16 at 06:49
  • Note 2: An array of `char` (such as the literal `"-B"`) does not decay to pointer-to-pointer. – Cheers and hth. - Alf Aug 09 '16 at 06:50
  • You probably need something like `char flag[] = "-B";` You can then pass the *address of* `flag` as `char **` by passing it as `myClass(2, &flag)` – David C. Rankin Aug 09 '16 at 07:34
  • @DavidC.Rankin you're missing a link : there should be a `char const *` pointing at flag[0]. Or, `char const *flag = "-B";`. – Quentin Aug 09 '16 at 07:40
  • Sure, that's fine, I just slept right by the declaration above `shhs...z...` – David C. Rankin Aug 09 '16 at 07:43
  • Prior comments already covered non-implicit conversion of `char**` to `const char**`, I don't in good conscience advise the following due to being [non-standard and potentially ub-abused](http://stackoverflow.com/questions/28116467/are-compound-literals-standard-c): a *compound literal*, if supported on your C++ toolchain (gcc and clang both do as extensions), may do what you seek, passing `(const char *[]){"arg0","arg1"}` for your second parameter. I certainly wouldn't, but your tolerance may differ from mine. – WhozCraig Aug 09 '16 at 09:00

2 Answers2

2

First level is pointer to first pointer to char *. Second level is pointer to the first const char of c-string.

> cdecl explain "const char ** args"
declare args as pointer to pointer to const char

If you have -std=c++11 available, you can use this example (but it can be rewritten to use old standard):

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

class test {
  public:
    test(const std::vector<std::string> & args) {
      for (auto & arg : args) {
        std::cout << arg << "\n";
      }
    }

    test() : test{{"-B"}} {}
};

int main(int argc, const char ** argv) {
  test sth{{argv+1, argc+argv}}; // skip program name here
  test sth_else;

}
KIIV
  • 3,534
  • 2
  • 18
  • 23
-1

const char** is pointer to const char*. In your case, you intend to pass multiple arguments as part of argv, so you can pass something like below:

const char* argv[] = {"<program name>", "B"};
myClass m(2, argv);

Note: const char** x & const char* x[] are same. The 2nd syntax is helpful when one wants to "represent" an array.

Here I am giving a way to mimic the main(int, char**) function argument for your internal test. If you want to pass from default constructor to argument constructor then all the above stuff will have to go global.

iammilind
  • 68,093
  • 33
  • 169
  • 336
  • Careful: in your example, `argv` *is not* a `const char**`, and the note doesn't explain this difference. – juanchopanza Aug 09 '16 at 07:00
  • There is no reason to believe the code in the question accurately represents the real code. It's a "like sort of this" example. That said, if you really think it's worth providing an answer, then I think you should address the incompatibility with the goal "which takes the main command line arguments". – Cheers and hth. - Alf Aug 09 '16 at 07:00
  • @juanchopanza, that's right & I have presented that in the answer. It seems that, the OP wants to pass those arguments to own class for further process. Moreover, `char**` in `main()` is for C legacy reason (the `const` didn't exist at that time). That's the reason, I presented `const char**`, because it's never intended to change `argv`. – iammilind Aug 09 '16 at 07:03
  • @Cheers, It seems that OP want to unit test the passing of arguments of `main` to own class using the delegation of constructor. `main()` accepts `char**` for legacy reasons, but in reality they should be treated as `const char**`. I have put that trivially in the code. If you feel that more explanation is required, feel free to comment here or edit answer as well. – iammilind Aug 09 '16 at 07:06