Why is implicit conversion not ambiguous for non-primitive types?Can you use keyword explicit to prevent...
Can you take a "free object interaction" while incapacitated?
Why is implicit conversion not ambiguous for non-primitive types?
I keep switching characters, how do I stop?
What is the period/term used describe Giuseppe Arcimboldo's style of painting?
What should be the ideal length of sentences in a blog post for ease of reading?
What is the meaning of "You've never met a graph you didn't like?"
Reasons for having MCU pin-states default to pull-up/down out of reset
New Order #2: Turn My Way
What is the tangent at a sharp point on a curve?
How do I lift the insulation blower into the attic?
How to preserve electronics (computers, ipads, phones) for hundreds of years?
Showing mass murder in a kid's book
How can a new country break out from a developed country without war?
If the Dominion rule using their Jem'Hadar troops, why is their life expectancy so low?
Are hand made posters acceptable in Academia?
Is there any common country to visit for persons holding UK and Schengen visas?
Extract substring according to regexp with sed or grep
How would a solely written language work mechanically
Highest stage count that are used one right after the other?
Pre-Employment Background Check With Consent For Future Checks
What do the positive and negative (+/-) transmit and receive pins mean on Ethernet cables?
Taking the numerator and the denominator
Checking @@ROWCOUNT failing
Is there a page on which I can view all Sitecore jobs running?
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?
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 (Bar{true});
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
add a comment |
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 (Bar{true});
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
1
Theexplicitkeyword is a nice thing. You should research it.
– Jesper Juhl
2 hours ago
e == fwill be ambiguous in C++20, for what its worth.
– Barry
2 hours ago
add a comment |
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 (Bar{true});
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
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 (Bar{true});
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
c++ templates c++17 implicit-conversion ambiguous
asked 3 hours ago
CybranCybran
1,047818
1,047818
1
Theexplicitkeyword is a nice thing. You should research it.
– Jesper Juhl
2 hours ago
e == fwill be ambiguous in C++20, for what its worth.
– Barry
2 hours ago
add a comment |
1
Theexplicitkeyword is a nice thing. You should research it.
– Jesper Juhl
2 hours ago
e == fwill be ambiguous in C++20, for what its worth.
– Barry
2 hours ago
1
1
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
2 hours ago
e == f will be ambiguous in C++20, for what its worth.– Barry
2 hours ago
add a comment |
2 Answers
2
active
oldest
votes
According to [over.binary]/1
Thus, for any binary operator
@,x@ycan be interpreted
as eitherx.operator@(y)oroperator@(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>.
add a comment |
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 (Bar{true});
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++.
add a comment |
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
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
According to [over.binary]/1
Thus, for any binary operator
@,x@ycan be interpreted
as eitherx.operator@(y)oroperator@(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>.
add a comment |
According to [over.binary]/1
Thus, for any binary operator
@,x@ycan be interpreted
as eitherx.operator@(y)oroperator@(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>.
add a comment |
According to [over.binary]/1
Thus, for any binary operator
@,x@ycan be interpreted
as eitherx.operator@(y)oroperator@(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>.
According to [over.binary]/1
Thus, for any binary operator
@,x@ycan be interpreted
as eitherx.operator@(y)oroperator@(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>.
answered 2 hours ago
BrianBrian
65.6k797186
65.6k797186
add a comment |
add a comment |
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 (Bar{true});
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++.
add a comment |
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 (Bar{true});
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++.
add a comment |
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 (Bar{true});
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++.
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 (Bar{true});
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++.
edited 2 hours ago
answered 2 hours ago
lubgrlubgr
13.8k32052
13.8k32052
add a comment |
add a comment |
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.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
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
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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
1
The
explicitkeyword is a nice thing. You should research it.– Jesper Juhl
2 hours ago
e == fwill be ambiguous in C++20, for what its worth.– Barry
2 hours ago