string operator + (const string &s, char *lit);
string operator + (const string &s, char *lit)
{
string temp;
temp.len = s.len+strlen(lit);
temp.str = new char[temp.len+1];
strcpy(temp.str, s.str);
strcat(tmep.str, lit);
return temp;
}
This is what my proffessor gave me as sample code as an example for overloading the string class. Thing is, when I compile it it says
std::string operator+(const string&, char*)’ must take either zero or one argument
I'm just wondering why it's not compiling? It'll take just one arg. but won't take two. Thanks.
I guess your professor meant namespace scope function (just usual function).
And you happened to declare non-static member function instead (I guess within some class named "blog").
operator+ accepts 1 or 2 arguments in namespace scope (binary operator+ accepts 2 arguments and unary operator+ accepts 1 argument) but as a non-static member function (in class scope) it accepts 0 or 1 argument (because it already has first implicit argument defined by this pointer).
Related
Everybody knows that you can't concatenate 2 string literals using the + operator.
#include <iostream>
int main() {
std::cout << "hello " + "world";
}
// Error
What's happening here is that you are trying to add 2 char* which is an error. You can however add a string literal to a std::string.
#include <iostream>
int main() {
std::string s = "hello ";
std::cout << s + "world";
}
// Fine, prints hello world
But what I found is that the below code is also valid.
#include <iostream>
int main() {
std::string s = "world";
std::cout << "hello " + s;
}
// Fine, prints hello world
I would imagine in the above example that you are trying to add a std::string to a char* but it works fine. I think it may just be using the std::string overload of the + operator. My question is what exactly is happening here and how does the operator decide which overload to use in a situation such as with 2 different classes with perfectly valid overloads being added together.
What's happening here is that you are trying to add 2 char* which is an error.
To be a bit more correct, you're trying to add two arrays, each of which decay to const char*.
My question is what exactly is happening here
You're using these overloads:
std::string
operator+(const std::string& lhs, const char* rhs);
std::string
operator+(const char* lhs, const std::string& rhs);
how does the operator decide which overload to use
It uses the same overload resolution as normal functions do. The complete and precise description won't fit within this answer since overload resolution is quite complex.
In short: There is a list of all functions by the same name. This is the overload set. If all arguments (operands in case of operator overload) can be converted to the formal parameters of the function, then that function is a viable candidate for the overload resolution. The candidates are ranked by a set of rules. Candidate requiring "less" conversion is ranked higher. If one candidate is unambiguously the most highly ranked candidate, then that overload will be called; otherwise there is an error.
Operator precedence : + has higher rank than <<, hence the line is parsed as:
(std::cout << ("hello " + s) );
And operator+(const char*,const std::string&) is the one on place 4 here: https://en.cppreference.com/w/cpp/string/basic_string/operator%2B.
Maybe you are a little surprised, because often operators are member functions and that implies that the left operand would need to be the std::string. However, thats not always the case. Operators can be free functions.
C++ primer, 6.7 pointer to functions Using auto or decltype for Function Pointer Types
If we know which function(s) we want to return, we can use decltype to simplify
writing a function pointer return type. For example, assume we have two functions, both of which return a string::size_type and have two const string&
parameters. We can write a third function that takes a string parameter and returns a pointer to one of these two functions as follows:
string::size_type sumLength(const string&, const string&);
string::size_type largerLength(const string&, const string&);
// depending on the value of its string parameter,
// getFcn returns a pointer to sumLength or to largerLength
decltype(sumLength) *getFcn(const string &);
I don't understand "depending on the value of its string parameter, getFcn returns a pointer to sumLength or to largerLength".
How do I know the pointer function returns point to sumLength or largerLength?
The passage is saying you can define getFcn as such
typedef decltype(sumLength) func_type;
func_type* getFcn(const string& s)
{
if (s.size() < 1000) // magic number
return sumLength;
else
return largerLength;
}
And you can call it like
string str1, str2;
// calls either sumLength or largerLength with str1, str2
// depending on str1's size
auto i = getFcn(str1)(str1, str2);
I posted a question earlier about how to overload strings, But when I use the same formula for unsigned long long it doesn't work.
I tried a typedef but that didn't work either.
typedef unsigned long long i64;
//a new class to hold extention types, and bytes.
class FileData
{
public:
//conversion operators
operator string(){return extensions_;}
operator i64() {return containsBytes_;}
string& operator= (FileData &);
i64& operator= (FileData &);
string extensions_;
i64 containsBytes_;
};
string &FileData::operator=(FileData& fd)
{
return fd.extensions_;
}
i64 &FileData::operator=(FileData& fd)
{
return fd.containsBytes_;
}
there are two errors in this code.
first one is on line 11:
Error:cannot overload functions distinguished by return types alone
second one is on line 22,
Error:declaration is incompatible with "std::string &FileData::operator=(FileData& fd)"(declared on line 17).
but if I delete any mention of the string conversion it still doesn't work.
I think what you are looking for is these
FileData& operator= (string&);
FileData& operator= (i64&);
FileData& FileData::operator=(string& s)
{
this->extensions_ = s;
return *this;
}
FileData& FileData::operator=(i64& l)
{
this->containsBytes_ = l;
return *this;
}
You are confusing assignment with type conversion operators. Assignment operator is used when you want to assign something to your class. Not to make it compatible with string or long long
With assignment for string overloaded you can do this
FileData a;
string str;
a = str; // This will set a.extensions_ to str, see above.
but not.
str = a;
Because assignment expects your class on the left hand side.
To do str = a; you need to overload conversion operators (). Which you have done.
operator string(){return extensions_;}
With those overloaded
str = a; // This will set str to a.extensions_ See the difference?
First error message
Error:cannot overload functions distinguished by return types alone
These two functions have identical parameters and differ only in return types
string& operator= (FileData &);
i64& operator= (FileData &);
C++ can overload functions only, when they differ in parameters.
Second error message
Error:declaration is incompatible with "std::string &FileData::operator=(FileData& fd)"(declared on line 17).
i64 &FileData::operator=(FileData& fd)
{
return fd.containsBytes_;
}
This is a follow up to the first error. The C++ compiler ignored the second assignment operator, because there was no differing parameters. Now, you define an assignment operator, which is incompatible with the assignment operator declared first above.
In some function calls I see stuff like this.
function(variable1, "someValue");
I have some questions based on this
1) How does c++ treat the second argument ?
2) if some function takes a cstring then why do we get error when we do the following
functionTakingCString(stringVariable.c_str() + "someValue");
Is there some way around instead of declaring a const char variable? Please correct me if I m wrong some where.
They are called string literals and if you want to take an argument that is a string literal like that you normally pass a const std::string& or a const char*, depending on what your API requires.
2) if some function takes a cstring then why do we get error when we do the following
That's because the '+' operator is not overloaded for char * type. You could concatenate it to stringVariable of type string for which the + operator has been overloaded to concatenate two strings, and then get the c_str() to pass to a function accepting char * or const char *.
const char*
Binary operator + cannot be applied on const char* operand types. If one is a std::string, then it works because of operator overloading.
The second argument is a const char*. In some cases you may be able convert from one type to another if you have a special converting constructor of the desired type that takes in the given type. The compiler can do this for you in some cases.
In this example string has a constructor that takes in a const char* so the compiler can turn a const char* into a string for you under the covers. If you want to stop this kind of behavior look into the explicit keyword.
The char* type isn't actually an class so it doesn't have a + operator that works for strings. However,
(stringVariable + "someValue").c_str()
will work because stringVariable is a string and it's plus operator can cooerce a char* into a string.
Why does the following not invoke the overloaded operator== (const String &, const String &)?
"cobble" == "stone"
Because in C++, string literals are of the type const char[] (also called a zero-terminated string constant), not std::string, let alone String (whatever that is).
There's a built-in operator== comparing two char* by comparing their addresses. Since arrays are implicitly convertible into pointers to their first elements (due, you guessed right, the C heritage), this operator steps in and what you compare are the addresses of these literals in memory.
Supposing your String class has an implicit conversion constructor from const char* (String::String(const char*)), you could convert one of the two to String. The other string would then be converted implicitly:
String("cobble") == "stone"
(Unless overloads of operator== taking a String and a const char* are provided for efficiency. If they are provided, they step in.)
Because implicitly existing operator==(char*, char*) matches your usage of == better.
The operator == in code "cobble" == "stone" can be matched in different ways: operator==(char[], const String&), operator==(const String&, String), operator==(const String&, const std::string&) etc., provided that the conversion from the parameter type (char*) to the type of arguments (String*, etc.) exists. However the usual char* comparison matches the input best of all.
Because those are simple sequences of characters as in C but no instances of the string class.
"cobble" ist interpreted as a char*, and the compiler uses pointer comparison to compare char*. If you want to compare the contents of the strings, use
std::string("cobble") == std::string("stone")
instead, and the compiler will use operator== (const std::string &, const std::string &).