Why is implicit conversion not ambiguous for non-primitive types?Can you use keyword explicit to prevent automatic conversion of method parameters?Why const for implicit conversion?Implicit conversion when overloading operators for template classesTemplate Constructor for Primitives, avoiding AmbiguityTemplate Type Deduction with Lambdasimplicit conversions from and to class typesConversion is ambiguous. Standard implicit conversion could not choose cast operatorGet type of implicit conversionImplicit conversion of stream to boolC++17: explicit conversion function vs explicit constructor + implicit conversions - have the rules changed?

A seasonal riddle

Center page as a whole without centering each element individually

What do the positive and negative (+/-) transmit and receive pins mean on Ethernet cables?

Are hand made posters acceptable in Academia?

How would a solely written language work mechanically

categorizing a variable turns it from insignificant to significant

Is there any common country to visit for persons holding UK and Schengen visas?

Why doesn't Gödel's incompleteness theorem apply to false statements?

"Marked down as someone wanting to sell shares." What does that mean?

Why is "la Gestapo" feminine?

Weird lines in Microsoft Word

Capacitor electron flow

Why does the frost depth increase when the surface temperature warms up?

Travelling in US for more than 90 days

What's the meaning of "what it means for something to be something"?

Why is indicated airspeed rather than ground speed used during the takeoff roll?

New Order #2: Turn My Way

Mortal danger in mid-grade literature

What is the tangent at a sharp point on a curve?

Relations between homogeneous polynomials

Offset in split text content

How do you say "Trust your struggle." in French?

How can an organ that provides biological immortality be unable to regenerate?

What is this high flying aircraft over Pennsylvania?



Why is implicit conversion not ambiguous for non-primitive types?


Can you use keyword explicit to prevent automatic conversion of method parameters?Why const for implicit conversion?Implicit conversion when overloading operators for template classesTemplate Constructor for Primitives, avoiding AmbiguityTemplate Type Deduction with Lambdasimplicit conversions from and to class typesConversion is ambiguous. Standard implicit conversion could not choose cast operatorGet type of implicit conversionImplicit conversion of stream to boolC++17: explicit conversion function vs explicit constructor + implicit conversions - have the rules changed?













7















Given a simple class template with multiple implicit conversion functions (non-explicit constructor and conversion operator), as in the following example:



template<class T>
class Foo

private:
T m_value;

public:
Foo();

Foo(const T& value):
m_value(value)



operator T() const
return m_value;


bool operator==(const Foo<T>& other) const
return m_value == other.m_value;

;

struct Bar

bool m;

bool operator==(const Bar& other) const
return false;

;

int main(int argc, char *argv[])

Foo<bool> a (true);
bool b = false;
if(a == b)
// This is ambiguous


Foo<int> c (1);
int d = 2;
if(c == d)
// This is ambiguous


Foo<Bar> e (Bartrue);
Bar f = false;
if(e == f)
// This is not ambiguous. Why?




The comparison operators involving primitive types (bool, int) are ambiguous, as expected - the compiler does not know whether it should use the conversion operator to convert the left-hand template class instance to a primitive type or use the conversion constructor to convert the right-hand primitive type to the expected class template instance.



However, the last comparison, involving a simple struct, is not ambiguous. Why? Which conversion function will be used?



Tested with compiler msvc 15.9.7.










share|improve this question






















  • The explicit keyword is a nice thing. You should research it.

    – Jesper Juhl
    2 hours ago











  • e == f will be ambiguous in C++20, for what its worth.

    – Barry
    1 hour ago















7















Given a simple class template with multiple implicit conversion functions (non-explicit constructor and conversion operator), as in the following example:



template<class T>
class Foo

private:
T m_value;

public:
Foo();

Foo(const T& value):
m_value(value)



operator T() const
return m_value;


bool operator==(const Foo<T>& other) const
return m_value == other.m_value;

;

struct Bar

bool m;

bool operator==(const Bar& other) const
return false;

;

int main(int argc, char *argv[])

Foo<bool> a (true);
bool b = false;
if(a == b)
// This is ambiguous


Foo<int> c (1);
int d = 2;
if(c == d)
// This is ambiguous


Foo<Bar> e (Bartrue);
Bar f = false;
if(e == f)
// This is not ambiguous. Why?




The comparison operators involving primitive types (bool, int) are ambiguous, as expected - the compiler does not know whether it should use the conversion operator to convert the left-hand template class instance to a primitive type or use the conversion constructor to convert the right-hand primitive type to the expected class template instance.



However, the last comparison, involving a simple struct, is not ambiguous. Why? Which conversion function will be used?



Tested with compiler msvc 15.9.7.










share|improve this question






















  • The explicit keyword is a nice thing. You should research it.

    – Jesper Juhl
    2 hours ago











  • e == f will be ambiguous in C++20, for what its worth.

    – Barry
    1 hour ago













7












7








7








Given a simple class template with multiple implicit conversion functions (non-explicit constructor and conversion operator), as in the following example:



template<class T>
class Foo

private:
T m_value;

public:
Foo();

Foo(const T& value):
m_value(value)



operator T() const
return m_value;


bool operator==(const Foo<T>& other) const
return m_value == other.m_value;

;

struct Bar

bool m;

bool operator==(const Bar& other) const
return false;

;

int main(int argc, char *argv[])

Foo<bool> a (true);
bool b = false;
if(a == b)
// This is ambiguous


Foo<int> c (1);
int d = 2;
if(c == d)
// This is ambiguous


Foo<Bar> e (Bartrue);
Bar f = false;
if(e == f)
// This is not ambiguous. Why?




The comparison operators involving primitive types (bool, int) are ambiguous, as expected - the compiler does not know whether it should use the conversion operator to convert the left-hand template class instance to a primitive type or use the conversion constructor to convert the right-hand primitive type to the expected class template instance.



However, the last comparison, involving a simple struct, is not ambiguous. Why? Which conversion function will be used?



Tested with compiler msvc 15.9.7.










share|improve this question














Given a simple class template with multiple implicit conversion functions (non-explicit constructor and conversion operator), as in the following example:



template<class T>
class Foo

private:
T m_value;

public:
Foo();

Foo(const T& value):
m_value(value)



operator T() const
return m_value;


bool operator==(const Foo<T>& other) const
return m_value == other.m_value;

;

struct Bar

bool m;

bool operator==(const Bar& other) const
return false;

;

int main(int argc, char *argv[])

Foo<bool> a (true);
bool b = false;
if(a == b)
// This is ambiguous


Foo<int> c (1);
int d = 2;
if(c == d)
// This is ambiguous


Foo<Bar> e (Bartrue);
Bar f = false;
if(e == f)
// This is not ambiguous. Why?




The comparison operators involving primitive types (bool, int) are ambiguous, as expected - the compiler does not know whether it should use the conversion operator to convert the left-hand template class instance to a primitive type or use the conversion constructor to convert the right-hand primitive type to the expected class template instance.



However, the last comparison, involving a simple struct, is not ambiguous. Why? Which conversion function will be used?



Tested with compiler msvc 15.9.7.







c++ templates c++17 implicit-conversion ambiguous






share|improve this question













share|improve this question











share|improve this question




share|improve this question










asked 2 hours ago









CybranCybran

1,047818




1,047818












  • The explicit keyword is a nice thing. You should research it.

    – Jesper Juhl
    2 hours ago











  • e == f will be ambiguous in C++20, for what its worth.

    – Barry
    1 hour ago

















  • The explicit keyword is a nice thing. You should research it.

    – Jesper Juhl
    2 hours ago











  • e == f will be ambiguous in C++20, for what its worth.

    – Barry
    1 hour ago
















The explicit keyword is a nice thing. You should research it.

– Jesper Juhl
2 hours ago





The explicit keyword is a nice thing. You should research it.

– Jesper Juhl
2 hours ago













e == f will be ambiguous in C++20, for what its worth.

– Barry
1 hour ago





e == f will be ambiguous in C++20, for what its worth.

– Barry
1 hour ago












2 Answers
2






active

oldest

votes


















10














According to [over.binary]/1




Thus, for any binary operator @, x@y can be interpreted
as either x.operator@(y) or operator@(x,y).




According to this rule, in the case of e == f, the compiler can only interpret it as e.operator==(f), not as f.operator==(e). So there is no ambiguity; the operator== you defined as a member of Bar is simply not a candidate for overload resolution.



In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.






share|improve this answer






























    2














    Operator overloads implemented as member functions don't allow for implicit conversion of their left hand side operand, which is the object on which they are called. It always helps to write down the explicit form of the operator overload to see what that means:



    Foo<Bar> e (Bartrue);
    Bar f = false;

    // Pretty explicit: call the member function Foo<Bar>::operator==
    if(e.operator ==(f)) /* ... */


    This can't be confused with the comparison operator in Bar, because it would require an implicit conversion of the left hand side operand, which is impossible. You can trigger an ambiguity similar to the ones you see with the builtin types when you define Bar and its comparison operator like this:



    struct Bar bool m; ;

    // A free function allows conversion, this will be ambigious:
    bool operator==(const Bar&, const Bar&)

    return false;



    This is nicely demonstrated and explained in Item 24, Scott Meyers, Effective C++.






    share|improve this answer
























      Your Answer






      StackExchange.ifUsing("editor", function ()
      StackExchange.using("externalEditor", function ()
      StackExchange.using("snippets", function ()
      StackExchange.snippets.init();
      );
      );
      , "code-snippets");

      StackExchange.ready(function()
      var channelOptions =
      tags: "".split(" "),
      id: "1"
      ;
      initTagRenderer("".split(" "), "".split(" "), channelOptions);

      StackExchange.using("externalEditor", function()
      // Have to fire editor after snippets, if snippets enabled
      if (StackExchange.settings.snippets.snippetsEnabled)
      StackExchange.using("snippets", function()
      createEditor();
      );

      else
      createEditor();

      );

      function createEditor()
      StackExchange.prepareEditor(
      heartbeatType: 'answer',
      autoActivateHeartbeat: false,
      convertImagesToLinks: true,
      noModals: true,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      imageUploader:
      brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
      contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
      allowUrls: true
      ,
      onDemand: true,
      discardSelector: ".discard-answer"
      ,immediatelyShowMarkdownHelp:true
      );



      );













      draft saved

      draft discarded


















      StackExchange.ready(
      function ()
      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55249017%2fwhy-is-implicit-conversion-not-ambiguous-for-non-primitive-types%23new-answer', 'question_page');

      );

      Post as a guest















      Required, but never shown

























      2 Answers
      2






      active

      oldest

      votes








      2 Answers
      2






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes









      10














      According to [over.binary]/1




      Thus, for any binary operator @, x@y can be interpreted
      as either x.operator@(y) or operator@(x,y).




      According to this rule, in the case of e == f, the compiler can only interpret it as e.operator==(f), not as f.operator==(e). So there is no ambiguity; the operator== you defined as a member of Bar is simply not a candidate for overload resolution.



      In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.






      share|improve this answer



























        10














        According to [over.binary]/1




        Thus, for any binary operator @, x@y can be interpreted
        as either x.operator@(y) or operator@(x,y).




        According to this rule, in the case of e == f, the compiler can only interpret it as e.operator==(f), not as f.operator==(e). So there is no ambiguity; the operator== you defined as a member of Bar is simply not a candidate for overload resolution.



        In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.






        share|improve this answer

























          10












          10








          10







          According to [over.binary]/1




          Thus, for any binary operator @, x@y can be interpreted
          as either x.operator@(y) or operator@(x,y).




          According to this rule, in the case of e == f, the compiler can only interpret it as e.operator==(f), not as f.operator==(e). So there is no ambiguity; the operator== you defined as a member of Bar is simply not a candidate for overload resolution.



          In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.






          share|improve this answer













          According to [over.binary]/1




          Thus, for any binary operator @, x@y can be interpreted
          as either x.operator@(y) or operator@(x,y).




          According to this rule, in the case of e == f, the compiler can only interpret it as e.operator==(f), not as f.operator==(e). So there is no ambiguity; the operator== you defined as a member of Bar is simply not a candidate for overload resolution.



          In the case of a == b and c == d, the built-in candidate operator==(int, int) (see [over.built]/13) competes with the operator== defined as a member of Foo<T>.







          share|improve this answer












          share|improve this answer



          share|improve this answer










          answered 2 hours ago









          BrianBrian

          65.6k797186




          65.6k797186























              2














              Operator overloads implemented as member functions don't allow for implicit conversion of their left hand side operand, which is the object on which they are called. It always helps to write down the explicit form of the operator overload to see what that means:



              Foo<Bar> e (Bartrue);
              Bar f = false;

              // Pretty explicit: call the member function Foo<Bar>::operator==
              if(e.operator ==(f)) /* ... */


              This can't be confused with the comparison operator in Bar, because it would require an implicit conversion of the left hand side operand, which is impossible. You can trigger an ambiguity similar to the ones you see with the builtin types when you define Bar and its comparison operator like this:



              struct Bar bool m; ;

              // A free function allows conversion, this will be ambigious:
              bool operator==(const Bar&, const Bar&)

              return false;



              This is nicely demonstrated and explained in Item 24, Scott Meyers, Effective C++.






              share|improve this answer





























                2














                Operator overloads implemented as member functions don't allow for implicit conversion of their left hand side operand, which is the object on which they are called. It always helps to write down the explicit form of the operator overload to see what that means:



                Foo<Bar> e (Bartrue);
                Bar f = false;

                // Pretty explicit: call the member function Foo<Bar>::operator==
                if(e.operator ==(f)) /* ... */


                This can't be confused with the comparison operator in Bar, because it would require an implicit conversion of the left hand side operand, which is impossible. You can trigger an ambiguity similar to the ones you see with the builtin types when you define Bar and its comparison operator like this:



                struct Bar bool m; ;

                // A free function allows conversion, this will be ambigious:
                bool operator==(const Bar&, const Bar&)

                return false;



                This is nicely demonstrated and explained in Item 24, Scott Meyers, Effective C++.






                share|improve this answer



























                  2












                  2








                  2







                  Operator overloads implemented as member functions don't allow for implicit conversion of their left hand side operand, which is the object on which they are called. It always helps to write down the explicit form of the operator overload to see what that means:



                  Foo<Bar> e (Bartrue);
                  Bar f = false;

                  // Pretty explicit: call the member function Foo<Bar>::operator==
                  if(e.operator ==(f)) /* ... */


                  This can't be confused with the comparison operator in Bar, because it would require an implicit conversion of the left hand side operand, which is impossible. You can trigger an ambiguity similar to the ones you see with the builtin types when you define Bar and its comparison operator like this:



                  struct Bar bool m; ;

                  // A free function allows conversion, this will be ambigious:
                  bool operator==(const Bar&, const Bar&)

                  return false;



                  This is nicely demonstrated and explained in Item 24, Scott Meyers, Effective C++.






                  share|improve this answer















                  Operator overloads implemented as member functions don't allow for implicit conversion of their left hand side operand, which is the object on which they are called. It always helps to write down the explicit form of the operator overload to see what that means:



                  Foo<Bar> e (Bartrue);
                  Bar f = false;

                  // Pretty explicit: call the member function Foo<Bar>::operator==
                  if(e.operator ==(f)) /* ... */


                  This can't be confused with the comparison operator in Bar, because it would require an implicit conversion of the left hand side operand, which is impossible. You can trigger an ambiguity similar to the ones you see with the builtin types when you define Bar and its comparison operator like this:



                  struct Bar bool m; ;

                  // A free function allows conversion, this will be ambigious:
                  bool operator==(const Bar&, const Bar&)

                  return false;



                  This is nicely demonstrated and explained in Item 24, Scott Meyers, Effective C++.







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited 1 hour ago

























                  answered 2 hours ago









                  lubgrlubgr

                  13.8k32052




                  13.8k32052



























                      draft saved

                      draft discarded
















































                      Thanks for contributing an answer to Stack Overflow!


                      • Please be sure to answer the question. Provide details and share your research!

                      But avoid


                      • Asking for help, clarification, or responding to other answers.

                      • Making statements based on opinion; back them up with references or personal experience.

                      To learn more, see our tips on writing great answers.




                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f55249017%2fwhy-is-implicit-conversion-not-ambiguous-for-non-primitive-types%23new-answer', 'question_page');

                      );

                      Post as a guest















                      Required, but never shown





















































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown

































                      Required, but never shown














                      Required, but never shown












                      Required, but never shown







                      Required, but never shown







                      Popular posts from this blog

                      Isabella Eugénie Boyer Biographie | Références | Menu de navigationmodifiermodifier le codeComparator to Compute the Relative Value of a U.S. Dollar Amount – 1774 to Present.

                      Join wedge with single bond in chemfigHow to make only one part of double bond bold with chemfig?Crossing bonds in chemfigjoining atoms in chemfig. Two adjacent molculesHow do I selectively change bond length in chemfig?Ugly bond joints in chemfigchemfig: reaction above arrowUsing the mhchem and chemfig packages in conjunctionBonding to specific element letter using chemfigResonance hybrids in chemfigScale chemfig molecule in beamer with tikzWhy does this chemfig bond with a hook start in the middle of the atom?

                      Are small insurances worth itIs insurance worth it if you can afford to replace the item? If not, when is it?Is accident insurance worth it for my kids who play sportsIs insuring property for more than it is worth allowed?At what point does it become worth it to file an insurance claim?Are wage loss insurance programs worth the cost compared to having an emergency fund?When is an event worth insuring against?Is insurance worth it if you can afford to replace the item? If not, when is it?FHA loan just commenced : Any way to get any of the up-front mortgage insurance back?Which types of insurances do I need to buy?Should I carry less renter's insurance if I can self-insure?Mortgage Adviser Signed Me Up For Multiple Home and Life Insurances (UK)Why many travel insurances don't cover country of nationality?