0

I have an example of two test programs I wrote in C++. The first one works fine, the first one errors. Please help me to explain what is going on here.

#include <iostream> #include <string> #include <stdint.h> #include <stdlib.h> #include <fstream> using namespace std; string randomStrGen(int length) { static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; string result; result.resize(length); for (int32_t i = 0; i < length; i++) result[i] = charset[rand() % charset.length()]; return result; } int main() { ofstream pConf; pConf.open("test.txt"); pConf << "rpcuser=user\nrpcpassword=" + randomStrGen(15) + "\nrpcport=14632" + "\nrpcallowip=127.0.0.1" + "\nport=14631" + "\ndaemon=1" + "\nserver=1" + "\naddnode=107.170.59.196"; pConf.close(); return 0; } 

It opens 'test.txt' and writes the data, no problem. This, however, does not:

#include <iostream> #include <string> #include <stdint.h> #include <stdlib.h> #include <fstream> using namespace std; string randomStrGen(int length) { static string charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"; string result; result.resize(length); for (int32_t i = 0; i < length; i++) result[i] = charset[rand() % charset.length()]; return result; } int main() { ofstream pConf; pConf.open("test.txt"); pConf << "rpcuser=user\n" + "rpcpassword=" + randomStrGen(15) + "\nrpcport=14632" + "\nrpcallowip=127.0.0.1" + "\nport=14631" + "\ndaemon=1" + "\nserver=1" + "\naddnode=107.170.59.196"; pConf.close(); return 0; } 

The only difference in the second program is that 'rpcpassword' has been moved to the next line.

matthew@matthew-Satellite-P845:~/Desktop$ g++ test.cpp test.cpp: In function ‘int main()’: test.cpp:23:6: error: invalid operands of types ‘const char [14]’ and ‘const char [13]’ to binary ‘operator+’ + "rpcpassword=" 
3
  • 1
    The difference is std::string has operator+ overloaded for concatenation with const char*. Commented Feb 6, 2015 at 1:14
  • Aasmund's answer's right, but incidentally adjacent string literals gets concatenated by the compiler in a pretty early phase (e.g. "abc" "def" becomes "abcdef", even if they're on different lines in the source). So, if you remove all the '+'s except those before and after randomStrGen(15), it will not only compile properly but use less memory and run faster. Commented Feb 6, 2015 at 1:21
  • FWIW - example using concatenation here... Commented Feb 6, 2015 at 1:31

2 Answers 2

5

A string literal ("foo") in C++ is not of the type string; it is of the type const char[x], where x is the length of the string literal plus 1. And character arrays can't be joined with +. However, a character array can be joined with a string, and the result is a string, which may further be joined with character arrays. Therefore, "a" + functionThatReturnsString() + "b" works, but "a" + "b" does not. (Keep in mind that + is left associative; it is applied to the two leftmost operands first, and then to the result and the third operand, and so on.)

Sign up to request clarification or add additional context in comments.

4 Comments

The OP should just remove the + as two consecutive string literals are automatically concatenated.
@user2676680 There are many non-member overloads for operator+ which take a const char* and a std::string. However, there is no built-in operator+ which takes two const char*s.
@user2676680 The last 2 sentences explain why the first one works
In case this did not become clear from @remyabel's comment: They are concatenated during translation of the program so it also has zero run-time overhead. If you don't have literals, you can replace your + with << but it will be less efficient in your current case.
4

"rpcuser=user\nrpcpassword=" + randomStrGen(15) + "\nrpcport=14632" groups like ("rpcuser=user\nrpcpassword=" + randomStrGen(15)) + "\nrpcport=14632". Here, + is always used with an argument of a class type, so you get std::string::operator+ after overload resolution.

"rpcuser=user\n" + "rpcpassword=" + randomStrGen(15) groups like ("rpcuser=user\n" + "rpcpassword=") + randomStrGen(15). In this case, the first + is used on two non-class types, so it's not overloaded and the language doesn't define + for two const char [] values. (I come from old C, so I was a bit it didn't just add them as char *s and give you a nice SIGSEGV at runtime.)

2 Comments

Both answers were very helpful, your groupings with the parentheses made it click. I don't like the fact that it is overloading without me knowing about it, it seems this will lead to programmers not knowing exactly what is going on. I will make sure to change my use of string literals.
I should have used parentheses to make my point more clear, so this gets an upvote from me too :-) (As long as you're using C++, you better get used to overloading...)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.