C++ const char* with string literal in method call [duplicate] - c++

This question already has answers here:
How to append const char* to a const char*
(3 answers)
Closed 2 years ago.
If I have a C++ function that takes a string parameter:
void somefunc(const std::string &s)
{
std::cout << ": " << s << std::endl;
}
If I then have something like:
const char *s = "This is a test...";
somefunc(s + "test");
I get an error:
error: invalid operands of types ‘const char*’ and ‘const char [5]’ to binary ‘operator+’
How can I call somefunc with s plus some other string?

Pointers (const char*) can't be added by operator+.
You can make either operand to std::string, to concatenate strings.
somefunc(std::string(s) + "test");
somefunc(s + std::string("test"));
Or use std::string literal.
using namespace std::string_literals;
somefun(s + "test"s);
// ^^^^^^^ <- std::string, not const char[5]

Related

Why is const char * overload chosen instead of std::string? [duplicate]

This question already has answers here:
Why {} is better candidate to be int than string for C++ overload resolution? [duplicate]
(1 answer)
Overload resolution with an empty brace initializer: pointer or reference? [duplicate]
(1 answer)
Closed 4 months ago.
In this code:
#include <string>
#include <iostream>
void my_function(const char* value)
{
std::cout << "char * " << (value ? value : "nullptr");
}
void my_function(const std::string &value)
{
std::cout << "string";
}
int main()
{
my_function({});
}
https://godbolt.org/z/56bxzjM1M
The const char * overload is chosen, passing a nullptr pointer. Can somebody explain why? I assume this is something weird with initializer lists? (By the way, this happens with my_function(string value) too, so it isn't the reference).
This caused a crash in our code because somebody added a const char * overload, causing the rare caller who passed {} to send in a nullptr.

correct way to pass ```const char* ptr``` to function, and make a copy of it in the function body

I am learning C++. I am trying to pass a string to a function via const char* str. I understand the basic meaning of this passing.
In the function body, when I try char * ptrStr = str, I got error: cannot initialize a variable of type 'char *' with an lvalue of type 'const char *'. But when I try auto ptrStr = str, it works.
I have two questions here: (1) could you please help explain why the former fails while the latter works? (2) how to use smart pointers here?
#include<iostream>
#include<memory>
void func(const char* str){
char* ptrStr = str;
}
/*
void func(const char* str){
auto ptrStr = str;
}
*/
int main(){
func("5486321 ");
return 0;
}

convert char* to const char* in C++

How to convert char* to const char* in C++? Why program 1 is working but program 2 can't?
Prog 1 (working):
char *s = "test string";
const char *tmp = s;
printMe(tmp);
void printMe(const char *&buf) {
printf("Given Str = %s", buf);
}
Prog 2 (not working)
char *s = "test string";
printMe((const char *)s); // typecasting not working
void printMe(const char *&buf) {
printf("Given Str = %s", buf);
}
The error I receive:
x.cpp:10:15: warning: conversion from string literal to 'char *' is
deprecated [-Wc++11-compat-deprecated-writable-strings]
char *s = "test string";
^
x.cpp:12:5: error: no matching function for call to 'printMe'
printMe(s);
^~~~~~~
x.cpp:6:6: note: candidate function not viable: no known conversion
from 'char *' to 'const char *&' for 1st argument
void printMe(const char *&buf)
^
1 warning and 1 error generated.
Thanks.
printMe takes an lvalue reference to a mutable pointer to const char.
In your first example, tmp is an lvalue of type mutable pointer to const char, so a reference can be bound to it without issue.
In your second example, (const char*)s creates a temporary const char* object. Lvalue references to mutable objects can't bind to temporaries, so you get an error. If you change printMe to take a const char* const& then the call will succeed with or without the explicit cast.
void printMe(const char * const& buf) {
printf("Given Str = %s", buf);
}
int main() {
char s[] = "test string";
printMe(s);
}
Live on Coliru
Of course, if you don't want to alter the object (the pointer) passed into printMe, then there's no reason to use a reference at all. Just make it take a const char*:
void printMe(const char * buf) {
printf("Given Str = %s", buf);
}
int main() {
char s[] = "test string";
printMe(s);
}
Live on Coliru
In the end, this is the same reason something like this:
void doSomething(const std::string& s) {}
int main() {
doSomething("asdf");
}
works while this:
void doSomething(std::string& s) {}
int main() {
doSomething("asdf");
}
does not. A temporary object is created, and the reference to non-const object can't bind to the temporary.

Coverting std::String to char * [duplicate]

This question already has answers here:
How to convert a std::string to const char* or char*
(11 answers)
std::string to char*
(18 answers)
Closed 9 years ago.
I need to pass string into socket send() function which accepts char * only. So here I am trying to convert it:
void myFunc(std::string str) //Taking string here const is good idea? I saw it on some examples on web
{
char *buf = str.c_str; //taking buf const is good idea?
std::cout << str;
}
int main()
{
const std::string str = "hello world";
myFunc(str);
return 0;
}
Gives error:
test.cpp:6:18: error: cannot convert ‘std::basic_string<_CharT, _Traits, _Alloc>::c_str<char, std::char_traits<char>, std::allocator<char> >’ from type ‘const char* (std::basic_string<char>::)()const’ to type ‘char*’
First off, c_str() is a function so you need to call it.
Second, it returns a const char* not a char*.
All in all:
const char* buf = str.c_str();
First of all, Call c_str() has a function.
After it, c_str() return a const char*, you need to copy it if you want to have a char* using std::strcpy() : http://en.cppreference.com/w/cpp/string/byte/strcpy
Try:
void myFunc(std::string str)
{
const char *buf = str.c_str();
std::cout << str;
}

C++: char** to const char** conversion [duplicate]

This question already has answers here:
Why am I getting an error converting a ‘float**’ to ‘const float**’?
(4 answers)
Closed 8 years ago.
In C++, why is it not possible to pass a char** as an argument to a function that accepts const char** , when a conversion from char* to const char* is possible, as shown below
void f1(const char** a)
{
}
void f2(const char* b)
{
}
int main(int argc, char const *argv[])
{
char* c;
f1(&c); // doesn't work
f2(c); //works
return 0;
}
The compiler output is
test.cpp: In function 'int main(int, const char**)':
test.cpp:15:10: error: invalid conversion from 'char**' to 'const char**' [-fpermissive]
test.cpp:1:6: error: initializing argument 1 of 'void f1(const char**)' [-fpermissive]
You need to protect contents on both levels of dereference of the pointer. With const char** you could actually modify contents on the 1st dereference.
char *tmp = "foo"; //Deprecated but it's ok for the example
void f1(const char** a)
{
a[0] = tmp; //this is legal
a[0][1] = 'x'; //this is not
}
And this is most probably not intended. It should look like this:
char *tmp = "foo"; //Deprecated but it's ok for the example
void f1(char const* const* a)
{
a[0] = tmp; // this is not legal any more
a[0][1] = 'x'; // this still upsets compiler
}
The compiler does not allow implicit conversion to such "partially" protected pointer types. Allowing such conversion could have nasty consequences as discussed in c++faq pointed out in comment by #zmb. This answer also cites how could you violate constness of an object if this was allowed, using char examples.
One can however implicitly convert to a "fully" protected pointer as shown in the 2nd code example so below code compiles.
void f1(char const* const* a){}
void f2(const char* b){}
int main(int argc, char const *argv[])
{
char* c;
f1(&c); // works now too!
f2(c); // works
return 0;
}
Actually there is a bunch of questions and answers on this matter lying around. E.g:
invalid conversion from ‘char**’ to ‘const char**’
Why am I getting an error converting a ‘float**’ to ‘const float**’?
EDIT: I got the 1st example wrong by a bit. Thank for pointing it out!