Troszke nagmatwałeś.
Sam błąd oznacza, że nie możesz zainicjować referencji niestałą r-wartoscia:
//blad kompilacji
String& s = String();
//wszystko cacy
const String& s2 = String();
r-wartość w tym przypadku to coś ulotnego co w normalnych warunkach przestaje istnieć w kolejnej linijce. Łapiąc ją przy pomocy referencji możesz przedłużyć jej życie, ale na modyfikowanie tego ulotnego obiektu jezyk juz nie pozwala.
Ale moment? Skąd u Ciebie rwartosci?
strncat zwraca char * a Twoja funkcja deklaruje zwracanie String& co powoduje, że tak na prawde zwracasz:
return String(strncat(str, plus.str, std::strlen(str)));
o ile istnieje konstruktor String(char *).
Żeby umożliwić łańcuchy możesz zwrócić obiekt przez wartość. Bo tak powinien działać operator +. Zwracać nowy obiekt a nie modyfikowac operandy:
string s1 = "paprykarz";
string s2 = "szczecinski ";
string s3 = s1 + s2;
//spodziewasz sie, ze
s1 == "paprykarz" && s2 == "szczecinski " && s3 == "paprykarz szczecinski"
//a w tym momencie s3 co prawda bedzie sie zgadzac ale s2 tez bedzie zmodyfikowane