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...)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.