Discussion:
Conversion operators: different behaviour for built-in types
(too old to reply)
Paul
2009-10-29 12:11:01 UTC
Permalink
struct Cref {
char c;
operator const char&() const { return c; }
};

struct Sref {
std::string s;
operator const std::string&() const { return s; }
};

int main()
{
Cref cr;
if (cr == 'a') return 1;

Sref sr;
if (sr == "a") return 2; // same if "a" is replced with std::string("a") or
const std::string&
}

The above code works for cr but not for sr and I wonder why and how to make
it work. I am trying to use a reference type in a way similar to how
Stroustrup does this for strings in his example (p. 296) and just stumbled
upon this.

Thank you.

Paul
Igor Tandetnik
2009-10-29 13:04:17 UTC
Permalink
Post by Paul
struct Cref {
char c;
operator const char&() const { return c; }
};
struct Sref {
std::string s;
operator const std::string&() const { return s; }
};
int main()
{
Cref cr;
if (cr == 'a') return 1;
Sref sr;
if (sr == "a") return 2; // same if "a" is replced with std::string("a") or
const std::string&
}
The above code works for cr but not for sr and I wonder why
There is a whole bunch of templated operator== implementations in scope. When deducing template parameters from arguments, user-defined conversions are not considered, and so none of them match.

On the other hand, a built-in == operator is treated essentially as a non-template function for the purposes of overloading resolution, and can accept user-defined conversions.
Post by Paul
and how to make
it work.
Why do you want to make it work? What are you trying to achieve? Is there any practical purpose for this?

For this particular case, instead of a conversion operator, you could define three overloads of operator==, taking (Sref, string), (string, Sref) and (Sref, Sref).
--
With best wishes,
Igor Tandetnik

With sufficient thrust, pigs fly just fine. However, this is not necessarily a good idea. It is hard to be sure where they are going to land, and it could be dangerous sitting under them as they fly overhead. -- RFC 1925
Paul
2009-10-29 14:09:01 UTC
Permalink
Post by Igor Tandetnik
There is a whole bunch of templated operator== implementations in scope. When deducing template parameters from arguments, user-defined conversions are not considered, and so none of them match.
On the other hand, a built-in == operator is treated essentially as a non-template function for the purposes of overloading resolution, and can accept user-defined conversions.
I forgot that

...bool operator ==(const ...string<...>&, const ...string<...>&)
...bool operator ==(const charT*, const ...string<...>&)
...bool operator ==(const ...string<...>&, const charT*)

are all templates.
Post by Igor Tandetnik
Why do you want to make it work? What are you trying to achieve? Is there any practical purpose for this?
For this particular case, instead of a conversion operator, you could define three overloads of operator==, taking (Sref, string), (string, Sref) and (Sref, Sref).
I had this implementation in mind:

class Message {
typedef std::map<int, std::string> Fields;
public:
class Fref;

//...

Fref operator [](int tag);
const std::string& operator [](int tag) const;
private:
std::string m_empty;
Fields m_fields;
};

class Message::Fref {
friend class Message;

Message& message;
int tag;

Fref(Message& m, int t) : message(m), tag(t) {}
Fref(const Fref& r) : message(r.message), tag(r.tag) {}

void operator =(const Fref&);
public:
operator const std::string&() const { return const_cast<const
Message&>(message)[tag]; }
void operator =(const std::string& v) { if (!v.empty())
message[tag] = v; }
};

inline Message::Fref Message::operator [](int tag)
{
return Fref(*this, tag);
}

inline const std::string& Message::operator [](int tag) const
{
Fields::const_iterator p = m_fields.find(tag);
return p != m_fields.end() ? p->second : m_empty;
}

and the idea, as in Stroustrup, was to use different semantics to read and
to write. Reading would just return a const std::string& to field data whilst
writing would check the value to write was not empty and would perform some
calculations (not shown) on the field being added or modified.

Thank you, Igor.
Rong-Chun Zhang [MSFT]
2009-10-30 10:10:05 UTC
Permalink
Hello Paul

The managed support service of the newsgroup microsoft.public.vc.language
is now available instead on [Visual C++ Language forum:
http://social.msdn.microsoft.com/Forums/en-US/vclanguage/threads/. Would
you please repost the question in the forum with the Windows Live ID used
to access your Subscription benefits? Our engineers will assist you in the
new platform. The article
http://msdn.microsoft.com/en-us/subscriptions/aa974230.aspx introduces more
information about the migration. In the future, please post your VC-related
questions directly to the forums. If you have any questions or concerns,
please feel free to contact us: ***@microsoft.com.

Regards,
Rongchun Zhang
Microsoft Online Community Support

Delighting our customers is our #1 priority. We welcome your comments and
suggestions about how we can improve the support we provide to you. Please
feel free to let my manager know what you think of the level of service
provided. You can send feedback directly to my manager at:
***@microsoft.com.

==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/en-us/subscriptions/aa948868.aspx#notifications.

MSDN Managed Newsgroup and Forum support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 2 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions. Issues of this
nature are best handled working with a dedicated Microsoft Support Engineer
by contacting Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/en-us/subscriptions/aa948874.aspx
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
Paul
2009-10-29 13:18:12 UTC
Permalink
Forgot to mention: this is the error message from the compiler:

1>.\....cpp(558) : error C2678: binary '==' : no operator found which takes
a left-hand operand of type 'Sref' (or there is no acceptable conversion)
1> could be 'built-in C++ operator==(const char [2], const char [2])'
1> C:\Program Files\Microsoft
SDKs\Windows\v6.0A\include\guiddef.h(192): or 'int operator ==(const
GUID &,const GUID &)'
1> while trying to match the argument list '(Sref, const char [2])'
Loading...