user-defined conversion combined with argument-dependent lookup

Discussion in 'C++' started by Belebele, Nov 30, 2007.

  1. Belebele

    Belebele Guest

    Suppose that I have a class that has a user-defined conversion to
    std::string, and I would like to compare objects of that class to
    "strings" (e.g. literals, std::strings):

    class InUpperCase {
    public:
    operator std::string() const;
    };

    ....
    InUpperCase()=="a string"; // This does not compile.
    // fine, bool operator==(InUpperCase const& , char const* );
    // is not declared anywhere.

    InUpperCase()==std::string("a string"); // This one does not compile
    either,
    // even though, there is a definition for an operator== in std
    // that takes two std::strings.

    I expected the second expression to compile fine due to ADL combined
    with the user-defined conversion. Any idea why?
    Belebele, Nov 30, 2007
    #1
    1. Advertising

  2. * Belebele:
    > Suppose that I have a class that has a user-defined conversion to
    > std::string, and I would like to compare objects of that class to
    > "strings" (e.g. literals, std::strings):
    >
    > class InUpperCase {
    > public:
    > operator std::string() const;
    > };
    >
    > ...
    > InUpperCase()=="a string"; // This does not compile.
    > // fine, bool operator==(InUpperCase const& , char const* );
    > // is not declared anywhere.
    >
    > InUpperCase()==std::string("a string"); // This one does not compile
    > either,
    > // even though, there is a definition for an operator== in std
    > // that takes two std::strings.
    >
    > I expected the second expression to compile fine due to ADL combined
    > with the user-defined conversion. Any idea why?


    Consider

    #include <string>

    struct Foo
    {
    operator std::string() const { return ""; }
    };

    template< typename Ch >
    void bar( std::basic_string<Ch> const& ) {}

    int main()
    {
    bar( Foo() );
    }

    Template matching doesn't succeed.

    When you're the one writing the bar() function you can always support
    future classes like Foo e.g. by making the argument a
    ConvertibleTo<std::string>, with each Foo class publicly derived from
    ConvertibleTo<std::string>.

    Cheers, & hth.,

    - Alf

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
    Alf P. Steinbach, Nov 30, 2007
    #2
    1. Advertising

  3. Belebele

    James Kanze Guest

    On Nov 30, 11:20 pm, Belebele <> wrote:
    > Suppose that I have a class that has a user-defined conversion to
    > std::string, and I would like to compare objects of that class to
    > "strings" (e.g. literals, std::strings):


    > class InUpperCase {
    > public:
    > operator std::string() const;
    > };


    > ...
    > InUpperCase()=="a string"; // This does not compile.
    > // fine, bool operator==(InUpperCase const& , char const* );
    > // is not declared anywhere.


    > InUpperCase()==std::string("a string"); // This one does not compile
    > either,
    > // even though, there is a definition for an operator== in std
    > // that takes two std::strings.


    > I expected the second expression to compile fine due to ADL combined
    > with the user-defined conversion. Any idea why?


    The problem is that there is no actual function available. The
    operator== defined on std::string are in fact templates, i.e.
    template< typename CharT, ... >
    bool
    operator==( std::basic_string< CharT, ... > const& ...
    In order for the operator to be available, the compiler must
    instantiate it because of type deduction, and type deduction
    doesn't take into account conversions (or only a very, very
    limited set of conversions, e.g. array to pointer, and such).

    If std::string weren't a template, then both of your examples
    would work, since there's also a comparison between std::string
    and char const*.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 2, 2007
    #3
  4. Belebele

    jg Guest

    On Dec 2, 1:19 am, James Kanze <> wrote:
    > On Nov 30, 11:20 pm, Belebele <> wrote:
    >
    >
    >
    > > Suppose that I have a class that has a user-defined conversion to
    > > std::string, and I would like to compare objects of that class to
    > > "strings" (e.g. literals, std::strings):
    > > classInUpperCase{
    > > public:
    > > operator std::string() const;
    > > };
    > > ...
    > >InUpperCase()=="a string"; // This does not compile.
    > > // fine, bool operator==(InUpperCaseconst& , char const* );
    > > // is not declared anywhere.
    > >InUpperCase()==std::string("a string"); // This one does not compile
    > > either,
    > > // even though, there is a definition for an operator== in std
    > > // that takes two std::strings.
    > > I expected the second expression to compile fine due to ADL combined
    > > with the user-defined conversion. Any idea why?

    >
    > The problem is that there is no actual function available. The
    > operator== defined on std::string are in fact templates, i.e.
    > template< typename CharT, ... >
    > bool
    > operator==( std::basic_string< CharT, ... > const& ...
    > In order for the operator to be available, the compiler must
    > instantiate it because of type deduction, and type deduction
    > doesn't take into account conversions (or only a very, very
    > limited set of conversions, e.g. array to pointer, and such).
    >
    > If std::string weren't a template, then both of your examples
    > would work, since there's also a comparison between std::string
    > and char const*.
    >
    > --
    > James Kanze (GABI Software) email:
    > Conseils en informatique orientée objet/
    > Beratung in objektorientierter Datenverarbeitung
    > 9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34


    On the same page, can this operator== be explicitly instantiated ?
    jg, Dec 5, 2007
    #4
  5. On Dec 1, 3:20 am, Belebele <> wrote:
    > Suppose that I have a class that has a user-defined conversion to
    > std::string, and I would like to compare objects of that class to
    > "strings" (e.g. literals, std::strings):
    >
    > class InUpperCase {
    > public:
    > operator std::string() const;
    >
    > };
    >


    Instead of providing a conversion operator, why don't you provide
    friend overload for operator== taking InUpperCase and std::string as
    arguments?
    Abhishek Padmanabh, Dec 5, 2007
    #5
  6. Belebele

    James Kanze Guest

    On Dec 5, 5:10 am, jg <> wrote:
    > On Dec 2, 1:19 am, James Kanze <> wrote:


    > On the same page, can this operator== be explicitly
    > instantiated ?


    I presume you mean the == operator for std::string. I think so,
    but I'll admit that I've never done it.

    I don't think that this will solve your problem, however. Even
    if explicitly instantiated, the compiler will use type deduction
    to determine whether the function is part of the overload set or
    not, and type deduction will fail in your case.

    The easiest solution is just to provide a simple wrapper in the
    form of an operator== which uses your class.

    --
    James Kanze (GABI Software) email:
    Conseils en informatique orientée objet/
    Beratung in objektorientierter Datenverarbeitung
    9 place Sémard, 78210 St.-Cyr-l'École, France, +33 (0)1 30 23 00 34
    James Kanze, Dec 5, 2007
    #6
  7. Belebele

    Belebele Guest

    > > class InUpperCase {
    > > public:
    > > operator std::string() const;

    >
    > > };

    >
    > Instead of providing a conversion operator, why don't you provide
    > friend overload for operator== taking InUpperCase and std::string as
    > arguments?


    My intention, besides being clarity of representation, is to take
    advantage of the existing facilities to avoid writing more boilerplate
    code (as long as I don't muddle the implementation too much along the
    way).

    That's why I avoided the friend overload if I could.
    Belebele, Dec 11, 2007
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Martin Vorbrodt

    argument dependent lookup

    Martin Vorbrodt, Oct 25, 2005, in forum: C++
    Replies:
    13
    Views:
    512
    Default User
    Oct 25, 2005
  2. siddhu

    Argument-Dependent Lookup

    siddhu, May 14, 2007, in forum: C++
    Replies:
    1
    Views:
    350
    Old Wolf
    May 14, 2007
  3. siddhu

    Argument-Dependent Lookup

    siddhu, May 14, 2007, in forum: C++
    Replies:
    4
    Views:
    475
    James Kanze
    May 15, 2007
  4. Replies:
    2
    Views:
    435
    Balog Pal
    Apr 9, 2009
  5. neverhoodboy
    Replies:
    1
    Views:
    442
    Johannes Schaub
    Mar 4, 2012
Loading...

Share This Page