Error: Invalid conversion from 'char**' to 'const char**'
Similar questions did not appear to have the same set of circumstances (ie two functions with different const requirements on the same structure). Please only mark this as a duplicate if it genuinely is.
ROS/C++: http://wiki.ros.org/ROS/Tutorials
Argument Parser: https://github.com/jamolnng/argparse
I need to pass argv
to a function from ROS and a function from the argparse
header. The former takes a char**
the latter takes a const *char[]
.
Code example (basic patterns are just taken from the examples for both libraries):
int main(int argc, char **argv){
argparse::ArgumentParser parser("Parser");
parser.add_argument()
.names({"-v", "--video"})
.description("Enable video output for this node.")
.required(false);
parser.enable_help();
//Problem 1: requires argv to be "const *char[]"
auto err = parser.parse(argc, argv);
if (err){ /*error handling*/}
//Problem 2: requires argv to be non-const
ros::init(argc, argv, "node_name");
...
return 0;
}
I need to call both of these functions but they both require different types for the same structure. Function prototypes for clarity:
//Declaration 1
Result parse(int argc, const char *argv[]);
//Declaration 2
void ros::init (int & argc,
char **argv,
const std::string &name,
uint32_t options = 0
);
Is there a way I can call both functions?
Why is this even a problem? So far as I understand the const
in Declaration 1 is just a promise that the function parse()
will not modify the argv
; why does this need the variable to be const
in the calling scope ( https://isocpp.org/wiki/faq/const-correctness ).
Edit - further information: On a hunch I tested a minimum working example without reference to either ROS or the argparsing libarary. Here is the test code:
#include <iostream>
void f(const char **a){
std::cout << a[1] << std::endl;
}
int main(int argc, char **argv){
// Attempt 1
f(argv); //Causes compilation error.
// Attempt 2
f(const_cast<const char**>(argv)); //No compilation error and correct functionality
return 0;
}
I further checked that the const_cast
resulted in the behaviour I desired (constness for the duration of the call to f()
and no more). Adapting Attempt 2 to the original problem solved my problem and I will add an answer below.
I am okay with the const_cast
here because I am elevating to const
and not trying to work around a data-structure which shouldn't be modified. That said I don't like const_cast
and I don't understand why it appears to be necessary in this case. I will leave the question open to see if anyone is willing to explain this (answer question 2 above), I'll post my functional solution.
This is a functional solution but I won't accept it as the answer until I have an explanation as to why this works or why this appeared to be necessary.
I changed:
auto err = parser.parse(argc, argv);
to
auto err = parser.parse(argc, const_cast<const char**>(argv));
Isolated testing (see edit) showed that this generated the behaviour I wanted and as far as I know is safe in this specific context. I do not think this is a "good" solution. I feel like const_cast
is a major code smell but I don't know enough to say why it would be bad in this case.
This solution also required the linking flag -lstdc++fs at compile time.
If you're using C++17 you can also try std::as_const() but I'm limited to C++11 at the moment.
First, I would think why non-const can't be implicitly converted to const: that would be unreliable, for instance, when deciding which overload to call. The contrary implicitly conversion is ok.
const_cast
is also for adding constness, not only for removing it. Then, const_cast
also helps to call a specific overload like in your case. I don't think it's a bad solution.
void f(char **a) {};
void f(const char *a[]) {};
int main(int argc, char **argv){
f(argv); //calls first f
f(const_cast<const char**>(argv)); //calls second f
}
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.