0

I have a function like this

void foo (const char* myString){
...
}

and I want to use it like this

std::string tail = "something";
foo("my" + "string" + tail);

But I just can't find an easy way. For sure I can make the string somewhere else and pass it to foo(). But I prefer to find a way to do it inline, because foo() is called several times in the code, I don't want to make a string for each time. I tried

foo(std::string ("my" + "string" + tail).c_str())

but you can guess that it doesn't work.

Sasan
  • 35
  • 7
  • What if you use `tail.c_str()`? – Dan Forbes Sep 29 '15 at 20:28
  • Why not use strcat()? – Kane Anderson Sep 29 '15 at 20:28
  • 4
    I suggest you take a look at this question: http://stackoverflow.com/questions/32555142/what-is-the-difference-between-these-two-cases-of-adding-a-string/32555209#32555209 – bku_drytt Sep 29 '15 at 20:29
  • @KaneAnderson: Because you have to allocate memory explicitly before you can use `strcat`. – Keith Thompson Sep 29 '15 at 20:29
  • In C++14 you can write `"my"s + "string" + tail` – M.M Sep 29 '15 at 20:30
  • String literals are automatically concatenated during compilation. Just remove the `+`. – Jonathon Reinhart Sep 29 '15 at 20:42
  • @M.M: And from my tests on this earlier, using C++14 string literals is almost always better than allowing C-style string literals to auto-promote. At least on `g++` 5.1 for Linux x64, the auto-promotion involves explicit runtime length calculations on the C-style string literal with code to handle errors related to the check, where using the C++14 literal syntax determines the necessary information at compile time, so construction boils down to fixed length allocation and `memcpy` and a hundred bytes or so fewer instructions. – ShadowRanger Sep 29 '15 at 22:30

5 Answers5

1

Just make sure "my" is a std::string, then you can use the std::string::operator+ operator on it. Later you use .c_str() on the resulting std::string.

Then, if you can change foo, the best is to make it accept const char*:

void foo (const char* myString)
{
    ...
}

std::string tail = "something";
foo( (std::string("my") + "string" + tail).c_str() );

If you can't change foo, then you'll have to do a cast because c_str() returns a const char* and foo wants a char*:

void foo (char* myString)
{
    ...
}

std::string tail = "something";
foo( const_cast<char*>( (std::string("my") + "string" + tail).c_str() ) );
jpo38
  • 20,821
  • 10
  • 70
  • 151
1

"my" and "string" are C-style strings. Their types are const char *, you cannot use operator + for these operands. But you can use this operator is any of the operands is string.

So the most elegant way for you it to add parenthesis:

foo(("my" + ("string" + tail)).c_str());

You will also have to change function foo to

void foo (const char* myString)
Andrey Nasonov
  • 2,619
  • 12
  • 26
1

"my"and "string" are C style string literals, which have the odd rule that they will be concatenated if they are written without a +.

So "my" "string" + tail will work, and produce a std::string. However, it will still not be the correct type for your function, unless you use .c_str() on the result.

Bo Persson
  • 90,663
  • 31
  • 146
  • 203
  • 1
    @Sasan: Your edit changes the entire nature of the question. That's a good example of why Stackoverflow prefers compilable example code. – Christian Hackl Sep 29 '15 at 20:50
  • @Cristian Hackl, I see! This was my first post on Stackoverflow, I'll do a better job next time! :) – Sasan Sep 29 '15 at 20:54
1

Your function accepts a modifiable array (not anymore, OP changed that in an edit) of char and std::string is not an array of char, but some unrelated object (that provides read-access to its internal char buffer, but that does not make it some kind of pretty array).

Additionally, using .c_str()-pointers into destroyed string objects is a common bug. Even if your function was to accept a const char* instead, you need to be aware that the pointer passed into it would only be valid until the end of the full expression the temporary std::string object was created in. This might or might not be what you want here, but is something you really need to watch out for. As I said, people get it wrong quite often.

So std::string probably (in the new const char* setting, it might) is not the right tool for this job as it is described right now. The best solution would be to make the argument of foo() an std::string (of some reference variant, depending on what it is doing). Then you can concatenate the inputs with + as long as one of the first summands already is an std::string.

If this should not be possible, copy the characters into an std::vector<char> which actually is the C++ way to get a char array (again, unlike string).

Baum mit Augen
  • 49,044
  • 25
  • 144
  • 182
  • Baum is correct, but I edited I already corrected my question. My function expects `const char*`. – Sasan Sep 29 '15 at 20:56
  • @Sasan Which then invalidated every upvoted answer at that time. That is at least bad style IMO. The answer still stands correct as is. – Baum mit Augen Sep 29 '15 at 20:59
0

The code foo("my" + "string" + tail); does not work for two reasons. First is order of operators. The code tries to execute "my" + "string", and since both of those are string literals, code fails. (you can not add up two string literals). The first issue is that if you magically make "my" + "string" working, code will concatenate it with tail, produce valid std::string, but fail to pass it to foo().

How to fix the issue?

  1. Change foo() signature. make it foo(const char* ) if you have to use char*, or, better, replace it with foo(const std::string&).
  2. Use following to concatenate: foo(std::string("my") + "string" + tail) if you followed my advice and made foo accepting const std::string&, or foo((std::string("my") + "string" + tail).c_str()) if you did not.
  3. On a side note, since both "my" and "string" are known at compile time, it's better to have simple foo("mystring" + tail) - easier to read, better performance.
SergeyA
  • 61,605
  • 5
  • 78
  • 137