I have been working on some question that involves converting ASCII value into string.
If I use this code, I get output as g
, which is expected.
using namespace std;
int main()
{
int i=6; vector<string> ans;
string t= "";
t =i 'a';
ans.push_back(t);
cout<<ans[0];
return 0;
}
However, If I change the code like this:
using namespace std;
int main()
{
int i=6; vector<string> ans;
string t= "";
t=t i 'a'; // <----
ans.push_back(t);
cout<<ans[0];
return 0;
}
The following error is shown, when I try to compile it:
error: no match for 'operator ' (operand types are 'std::string' {aka 'std::__cxx11::basic_string<char>'} and 'int')
7 | t=t i 'a';
| ~^~
| | |
| | int
| std::string {aka std::__cxx11::basic_string<char>}
The only difference between both the code is that in 1st code, I am using t =i 'a';
, while in second, t=t i 'a';
is used.
Can someone please tell what is wrong with the second snippet?
CodePudding user response:
1. The t = i 'a';
case
Here, two things are important. First,
std::string& std::string::operator =(char ch);
is called, which is a non-template member function of the std::string
class (that is, of the std::basic_string<char>
class template instance); see https://en.cppreference.com/w/cpp/string/basic_string/operator+=.
Second, the type of i 'a'
is int
.
Everything works fine, since the argument i 'a'
of type int
can be used as an argument for a function parameter of type char
.
2. The t = t i 'a';
case
In contrast to case 1., operator
is used here. First for the t i
part, where i
is of type int
(see @AnoopRana's answer for details of why). But opeartor
is a free (non-member) function template; see https://en.cppreference.com/w/cpp/string/basic_string/operator+.
The compiler tries to instantiate this definition:
template<class CharT, class Traits, class Alloc>
std::basic_string<CharT,Traits,Alloc>
operator ( const std::basic_string<CharT,Traits,Alloc>& lhs, CharT rhs );
But it can't since:
- according to the first argument of type
std::string
,CharT
would be deduced aschar
, - according to the second argument of type
int
,CharT
would be deduced asint
.
Therefore, duduction conflict happens. And, there is no other template that might be instantiated.
Simple demo code of the same problem:
template <typename Char>
struct String
{
String& operator =(Char);
};
template <typename Char>
String<Char> operator (const String<Char>&, Char);
int main()
{
String<char> s;
s = 2 'a';
s = s 2 'a';
}
Live link: https://godbolt.org/z/MonK1e3bq
CodePudding user response:
The problem in case 2 is that the statement t = t i 'a'
is actually grouped as(or equivalent to) t = (t i) 'a'
due to operator precedence.
//---v---v--------->t is std::string while i is an int
t = (t i) 'a'; //equivalent to this due to operator precedence
Now as t
is a std::string
and i
is an int
and since there is no overloaded operator
that takes an std::string
and a int
, we get the mentioned error.
Note that
is an arithmetic operator and so in the first case, the character literal 'a'
is promoted to int
when writing i 'a'
. And since std::string
has the overload string& string::operator = (char)
that can be used, the first case uses that overloaded operator =
.