GCC can't differentiate between operator++() and operator++(int)












54














template <typename CRTP>
struct Pre {
CRTP & operator++();
};

template <typename CRTP>
struct Post {
CRTP operator++(int);
};

struct Derived
: Pre<Derived>
, Post<Derived>
{};

int main() {
Derived d;
d++;
++d;
}


I get these errors from GCC:



<source>: In function 'int main()':
<source>:18:10: error: request for member 'operator++' is ambiguous
d++;
^~
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~
<source>:19:11: error: request for member 'operator++' is ambiguous
++d;
^
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~


Pre-decrement and post-decrement operators cause similar errors. No such errors with Clang. Any ideas what could be wrong or how to work around this?










share|improve this question




















  • 6




    using Pre::operator++; using Post::operator++; works, but I guess it defeats the purpose of your CRTP...
    – Quentin
    yesterday






  • 1




    fwiw also with supplying the implementation and also without crtp gcc reports the error
    – user463035818
    yesterday








  • 3




    @Quentin Puts using declaration in a helper template PrePost : Pre, Post
    – felix
    yesterday






  • 7




    For me behavior of gcc seems to be correct. Invocation of function operator ++ should not compile because it is not clear to which function does the name operator ++ refer to.
    – VTT
    yesterday






  • 2




    It's not a defect in the sense that the language itself has an inconsistency that needs resolution. It's only a design choice with unfortunate consequences, a colloquial defect, if you were.
    – StoryTeller
    yesterday
















54














template <typename CRTP>
struct Pre {
CRTP & operator++();
};

template <typename CRTP>
struct Post {
CRTP operator++(int);
};

struct Derived
: Pre<Derived>
, Post<Derived>
{};

int main() {
Derived d;
d++;
++d;
}


I get these errors from GCC:



<source>: In function 'int main()':
<source>:18:10: error: request for member 'operator++' is ambiguous
d++;
^~
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~
<source>:19:11: error: request for member 'operator++' is ambiguous
++d;
^
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~


Pre-decrement and post-decrement operators cause similar errors. No such errors with Clang. Any ideas what could be wrong or how to work around this?










share|improve this question




















  • 6




    using Pre::operator++; using Post::operator++; works, but I guess it defeats the purpose of your CRTP...
    – Quentin
    yesterday






  • 1




    fwiw also with supplying the implementation and also without crtp gcc reports the error
    – user463035818
    yesterday








  • 3




    @Quentin Puts using declaration in a helper template PrePost : Pre, Post
    – felix
    yesterday






  • 7




    For me behavior of gcc seems to be correct. Invocation of function operator ++ should not compile because it is not clear to which function does the name operator ++ refer to.
    – VTT
    yesterday






  • 2




    It's not a defect in the sense that the language itself has an inconsistency that needs resolution. It's only a design choice with unfortunate consequences, a colloquial defect, if you were.
    – StoryTeller
    yesterday














54












54








54


9





template <typename CRTP>
struct Pre {
CRTP & operator++();
};

template <typename CRTP>
struct Post {
CRTP operator++(int);
};

struct Derived
: Pre<Derived>
, Post<Derived>
{};

int main() {
Derived d;
d++;
++d;
}


I get these errors from GCC:



<source>: In function 'int main()':
<source>:18:10: error: request for member 'operator++' is ambiguous
d++;
^~
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~
<source>:19:11: error: request for member 'operator++' is ambiguous
++d;
^
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~


Pre-decrement and post-decrement operators cause similar errors. No such errors with Clang. Any ideas what could be wrong or how to work around this?










share|improve this question















template <typename CRTP>
struct Pre {
CRTP & operator++();
};

template <typename CRTP>
struct Post {
CRTP operator++(int);
};

struct Derived
: Pre<Derived>
, Post<Derived>
{};

int main() {
Derived d;
d++;
++d;
}


I get these errors from GCC:



<source>: In function 'int main()':
<source>:18:10: error: request for member 'operator++' is ambiguous
d++;
^~
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~
<source>:19:11: error: request for member 'operator++' is ambiguous
++d;
^
<source>:8:14: note: candidates are: CRTP Post<CRTP>::operator++(int) [with CRTP = Derived]
CRTP operator++(int);
^~~~~~~~
<source>:3:16: note: CRTP& Pre<CRTP>::operator++() [with CRTP = Derived]
CRTP & operator++();
^~~~~~~~


Pre-decrement and post-decrement operators cause similar errors. No such errors with Clang. Any ideas what could be wrong or how to work around this?







c++ operator-overloading multiple-inheritance ambiguous






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited yesterday







jotik

















asked yesterday









jotikjotik

8,58963792




8,58963792








  • 6




    using Pre::operator++; using Post::operator++; works, but I guess it defeats the purpose of your CRTP...
    – Quentin
    yesterday






  • 1




    fwiw also with supplying the implementation and also without crtp gcc reports the error
    – user463035818
    yesterday








  • 3




    @Quentin Puts using declaration in a helper template PrePost : Pre, Post
    – felix
    yesterday






  • 7




    For me behavior of gcc seems to be correct. Invocation of function operator ++ should not compile because it is not clear to which function does the name operator ++ refer to.
    – VTT
    yesterday






  • 2




    It's not a defect in the sense that the language itself has an inconsistency that needs resolution. It's only a design choice with unfortunate consequences, a colloquial defect, if you were.
    – StoryTeller
    yesterday














  • 6




    using Pre::operator++; using Post::operator++; works, but I guess it defeats the purpose of your CRTP...
    – Quentin
    yesterday






  • 1




    fwiw also with supplying the implementation and also without crtp gcc reports the error
    – user463035818
    yesterday








  • 3




    @Quentin Puts using declaration in a helper template PrePost : Pre, Post
    – felix
    yesterday






  • 7




    For me behavior of gcc seems to be correct. Invocation of function operator ++ should not compile because it is not clear to which function does the name operator ++ refer to.
    – VTT
    yesterday






  • 2




    It's not a defect in the sense that the language itself has an inconsistency that needs resolution. It's only a design choice with unfortunate consequences, a colloquial defect, if you were.
    – StoryTeller
    yesterday








6




6




using Pre::operator++; using Post::operator++; works, but I guess it defeats the purpose of your CRTP...
– Quentin
yesterday




using Pre::operator++; using Post::operator++; works, but I guess it defeats the purpose of your CRTP...
– Quentin
yesterday




1




1




fwiw also with supplying the implementation and also without crtp gcc reports the error
– user463035818
yesterday






fwiw also with supplying the implementation and also without crtp gcc reports the error
– user463035818
yesterday






3




3




@Quentin Puts using declaration in a helper template PrePost : Pre, Post
– felix
yesterday




@Quentin Puts using declaration in a helper template PrePost : Pre, Post
– felix
yesterday




7




7




For me behavior of gcc seems to be correct. Invocation of function operator ++ should not compile because it is not clear to which function does the name operator ++ refer to.
– VTT
yesterday




For me behavior of gcc seems to be correct. Invocation of function operator ++ should not compile because it is not clear to which function does the name operator ++ refer to.
– VTT
yesterday




2




2




It's not a defect in the sense that the language itself has an inconsistency that needs resolution. It's only a design choice with unfortunate consequences, a colloquial defect, if you were.
– StoryTeller
yesterday




It's not a defect in the sense that the language itself has an inconsistency that needs resolution. It's only a design choice with unfortunate consequences, a colloquial defect, if you were.
– StoryTeller
yesterday












1 Answer
1






active

oldest

votes


















60














Name lookup must occur first. In this case for the name operator++.




[basic.lookup] (emphasis mine)



1 The name lookup rules apply uniformly to all names (including
typedef-names ([dcl.typedef]), namespace-names ([basic.namespace]),
and class-names ([class.name])) wherever the grammar allows such names
in the context discussed by a particular rule. Name lookup associates
the use of a name with a declaration ([basic.def]) of that name. Name
lookup shall find an unambiguous declaration for the name (see
[class.member.lookup])
. Name lookup may associate more than one
declaration with a name if it finds the name to be a function name;
the declarations are said to form a set of overloaded functions
([over.load]). Overload resolution ([over.match]) takes place after
name lookup has succeeded
. The access rules (Clause [class.access])
are considered only once name lookup and function overload resolution
(if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded
are the attributes introduced by the name's declaration used further
in expression processing (Clause [expr]).




And only if the lookup is unambiguous, will overload resolution proceed. In this case, the name is found in the scope of two different classes, and so an ambiguity is present even prior to overload resolution.




[class.member.lookup]



8 If the name of an overloaded function is unambiguously found,
overloading resolution ([over.match]) also takes place before access
control. Ambiguities can often be resolved by qualifying a name with
its class name. [ Example:



struct A {
int f();
};

struct B {
int f();
};

struct C : A, B {
int f() { return A::f() + B::f(); }
};


— end example ]




The example pretty much summarizes the rather long lookup rules in the previous paragraphs of [class.member.lookup]. There is an ambiguity in your code. GCC is correct to report it.





As for working around this, people in comments already presented the ideas for a workaround. Add a helper CRTP class



template <class CRTP>
struct PrePost
: Pre<CRTP>
, Post<CRTP>
{
using Pre<CRTP>::operator++;
using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};


The name is now found in the scope of a single class, and names both overloads. Lookup is successful, and overload resolution may proceed.






share|improve this answer



















  • 12




    Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
    – WhozCraig
    yesterday








  • 4




    @StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
    – Arne Vogel
    yesterday






  • 3




    Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
    – Walter
    yesterday








  • 1




    @Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
    – StoryTeller
    yesterday








  • 2




    @PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
    – StoryTeller
    yesterday











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%2f54091513%2fgcc-cant-differentiate-between-operator-and-operatorint%23new-answer', 'question_page');
}
);

Post as a guest















Required, but never shown

























1 Answer
1






active

oldest

votes








1 Answer
1






active

oldest

votes









active

oldest

votes






active

oldest

votes









60














Name lookup must occur first. In this case for the name operator++.




[basic.lookup] (emphasis mine)



1 The name lookup rules apply uniformly to all names (including
typedef-names ([dcl.typedef]), namespace-names ([basic.namespace]),
and class-names ([class.name])) wherever the grammar allows such names
in the context discussed by a particular rule. Name lookup associates
the use of a name with a declaration ([basic.def]) of that name. Name
lookup shall find an unambiguous declaration for the name (see
[class.member.lookup])
. Name lookup may associate more than one
declaration with a name if it finds the name to be a function name;
the declarations are said to form a set of overloaded functions
([over.load]). Overload resolution ([over.match]) takes place after
name lookup has succeeded
. The access rules (Clause [class.access])
are considered only once name lookup and function overload resolution
(if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded
are the attributes introduced by the name's declaration used further
in expression processing (Clause [expr]).




And only if the lookup is unambiguous, will overload resolution proceed. In this case, the name is found in the scope of two different classes, and so an ambiguity is present even prior to overload resolution.




[class.member.lookup]



8 If the name of an overloaded function is unambiguously found,
overloading resolution ([over.match]) also takes place before access
control. Ambiguities can often be resolved by qualifying a name with
its class name. [ Example:



struct A {
int f();
};

struct B {
int f();
};

struct C : A, B {
int f() { return A::f() + B::f(); }
};


— end example ]




The example pretty much summarizes the rather long lookup rules in the previous paragraphs of [class.member.lookup]. There is an ambiguity in your code. GCC is correct to report it.





As for working around this, people in comments already presented the ideas for a workaround. Add a helper CRTP class



template <class CRTP>
struct PrePost
: Pre<CRTP>
, Post<CRTP>
{
using Pre<CRTP>::operator++;
using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};


The name is now found in the scope of a single class, and names both overloads. Lookup is successful, and overload resolution may proceed.






share|improve this answer



















  • 12




    Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
    – WhozCraig
    yesterday








  • 4




    @StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
    – Arne Vogel
    yesterday






  • 3




    Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
    – Walter
    yesterday








  • 1




    @Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
    – StoryTeller
    yesterday








  • 2




    @PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
    – StoryTeller
    yesterday
















60














Name lookup must occur first. In this case for the name operator++.




[basic.lookup] (emphasis mine)



1 The name lookup rules apply uniformly to all names (including
typedef-names ([dcl.typedef]), namespace-names ([basic.namespace]),
and class-names ([class.name])) wherever the grammar allows such names
in the context discussed by a particular rule. Name lookup associates
the use of a name with a declaration ([basic.def]) of that name. Name
lookup shall find an unambiguous declaration for the name (see
[class.member.lookup])
. Name lookup may associate more than one
declaration with a name if it finds the name to be a function name;
the declarations are said to form a set of overloaded functions
([over.load]). Overload resolution ([over.match]) takes place after
name lookup has succeeded
. The access rules (Clause [class.access])
are considered only once name lookup and function overload resolution
(if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded
are the attributes introduced by the name's declaration used further
in expression processing (Clause [expr]).




And only if the lookup is unambiguous, will overload resolution proceed. In this case, the name is found in the scope of two different classes, and so an ambiguity is present even prior to overload resolution.




[class.member.lookup]



8 If the name of an overloaded function is unambiguously found,
overloading resolution ([over.match]) also takes place before access
control. Ambiguities can often be resolved by qualifying a name with
its class name. [ Example:



struct A {
int f();
};

struct B {
int f();
};

struct C : A, B {
int f() { return A::f() + B::f(); }
};


— end example ]




The example pretty much summarizes the rather long lookup rules in the previous paragraphs of [class.member.lookup]. There is an ambiguity in your code. GCC is correct to report it.





As for working around this, people in comments already presented the ideas for a workaround. Add a helper CRTP class



template <class CRTP>
struct PrePost
: Pre<CRTP>
, Post<CRTP>
{
using Pre<CRTP>::operator++;
using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};


The name is now found in the scope of a single class, and names both overloads. Lookup is successful, and overload resolution may proceed.






share|improve this answer



















  • 12




    Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
    – WhozCraig
    yesterday








  • 4




    @StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
    – Arne Vogel
    yesterday






  • 3




    Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
    – Walter
    yesterday








  • 1




    @Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
    – StoryTeller
    yesterday








  • 2




    @PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
    – StoryTeller
    yesterday














60












60








60






Name lookup must occur first. In this case for the name operator++.




[basic.lookup] (emphasis mine)



1 The name lookup rules apply uniformly to all names (including
typedef-names ([dcl.typedef]), namespace-names ([basic.namespace]),
and class-names ([class.name])) wherever the grammar allows such names
in the context discussed by a particular rule. Name lookup associates
the use of a name with a declaration ([basic.def]) of that name. Name
lookup shall find an unambiguous declaration for the name (see
[class.member.lookup])
. Name lookup may associate more than one
declaration with a name if it finds the name to be a function name;
the declarations are said to form a set of overloaded functions
([over.load]). Overload resolution ([over.match]) takes place after
name lookup has succeeded
. The access rules (Clause [class.access])
are considered only once name lookup and function overload resolution
(if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded
are the attributes introduced by the name's declaration used further
in expression processing (Clause [expr]).




And only if the lookup is unambiguous, will overload resolution proceed. In this case, the name is found in the scope of two different classes, and so an ambiguity is present even prior to overload resolution.




[class.member.lookup]



8 If the name of an overloaded function is unambiguously found,
overloading resolution ([over.match]) also takes place before access
control. Ambiguities can often be resolved by qualifying a name with
its class name. [ Example:



struct A {
int f();
};

struct B {
int f();
};

struct C : A, B {
int f() { return A::f() + B::f(); }
};


— end example ]




The example pretty much summarizes the rather long lookup rules in the previous paragraphs of [class.member.lookup]. There is an ambiguity in your code. GCC is correct to report it.





As for working around this, people in comments already presented the ideas for a workaround. Add a helper CRTP class



template <class CRTP>
struct PrePost
: Pre<CRTP>
, Post<CRTP>
{
using Pre<CRTP>::operator++;
using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};


The name is now found in the scope of a single class, and names both overloads. Lookup is successful, and overload resolution may proceed.






share|improve this answer














Name lookup must occur first. In this case for the name operator++.




[basic.lookup] (emphasis mine)



1 The name lookup rules apply uniformly to all names (including
typedef-names ([dcl.typedef]), namespace-names ([basic.namespace]),
and class-names ([class.name])) wherever the grammar allows such names
in the context discussed by a particular rule. Name lookup associates
the use of a name with a declaration ([basic.def]) of that name. Name
lookup shall find an unambiguous declaration for the name (see
[class.member.lookup])
. Name lookup may associate more than one
declaration with a name if it finds the name to be a function name;
the declarations are said to form a set of overloaded functions
([over.load]). Overload resolution ([over.match]) takes place after
name lookup has succeeded
. The access rules (Clause [class.access])
are considered only once name lookup and function overload resolution
(if applicable) have succeeded. Only after name lookup, function
overload resolution (if applicable) and access checking have succeeded
are the attributes introduced by the name's declaration used further
in expression processing (Clause [expr]).




And only if the lookup is unambiguous, will overload resolution proceed. In this case, the name is found in the scope of two different classes, and so an ambiguity is present even prior to overload resolution.




[class.member.lookup]



8 If the name of an overloaded function is unambiguously found,
overloading resolution ([over.match]) also takes place before access
control. Ambiguities can often be resolved by qualifying a name with
its class name. [ Example:



struct A {
int f();
};

struct B {
int f();
};

struct C : A, B {
int f() { return A::f() + B::f(); }
};


— end example ]




The example pretty much summarizes the rather long lookup rules in the previous paragraphs of [class.member.lookup]. There is an ambiguity in your code. GCC is correct to report it.





As for working around this, people in comments already presented the ideas for a workaround. Add a helper CRTP class



template <class CRTP>
struct PrePost
: Pre<CRTP>
, Post<CRTP>
{
using Pre<CRTP>::operator++;
using Post<CRTP>::operator++;
};

struct Derived : PrePost<Derived> {};


The name is now found in the scope of a single class, and names both overloads. Lookup is successful, and overload resolution may proceed.







share|improve this answer














share|improve this answer



share|improve this answer








edited yesterday

























answered yesterday









StoryTellerStoryTeller

94.4k12191254




94.4k12191254








  • 12




    Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
    – WhozCraig
    yesterday








  • 4




    @StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
    – Arne Vogel
    yesterday






  • 3




    Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
    – Walter
    yesterday








  • 1




    @Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
    – StoryTeller
    yesterday








  • 2




    @PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
    – StoryTeller
    yesterday














  • 12




    Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
    – WhozCraig
    yesterday








  • 4




    @StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
    – Arne Vogel
    yesterday






  • 3




    Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
    – Walter
    yesterday








  • 1




    @Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
    – StoryTeller
    yesterday








  • 2




    @PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
    – StoryTeller
    yesterday








12




12




Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
– WhozCraig
yesterday






Fwiw, MS VS2015 (19.00.24215.1) complains about the ambiguity via IntelliNonsense, but then still compiles the code to success (with no warnings or errors) and executes the hoped-for members at run-time.
– WhozCraig
yesterday






4




4




@StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
– Arne Vogel
yesterday




@StoryTeller Indeed, for a "normal" method f() vs. f(int), clang++ complains about: "error: member 'f' found in multiple base classes of different types" and adds "note: member found by ambiguous name lookup". GCC is actually more consistent here.
– Arne Vogel
yesterday




3




3




Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
– Walter
yesterday






Ok. So it appears that this is sort-of a defect in the language (that d++ and ++d refer to the same operator/function name), which gcc faithfully implements, while clang and VS17 appear to implement what the user obviously intended (even w/o warning).
– Walter
yesterday






1




1




@Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
– StoryTeller
yesterday






@Walter - Pretty much. Had we taken a path like, say, Python with regards to overloading, it'd had probably been easier to work with all around. Alas, something else was choesn.
– StoryTeller
yesterday






2




2




@PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
– StoryTeller
yesterday




@PiotrNycz - Other than being called by a special syntax, overloaded operators are regular functions. As a matter of fact, they can also be called just like regular functions. d.operator++(0) will cause this ambiguity, as should d++, since the two are exactly equivalent.
– StoryTeller
yesterday


















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.





Some of your past answers have not been well-received, and you're in danger of being blocked from answering.


Please pay close attention to the following guidance:


  • 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%2f54091513%2fgcc-cant-differentiate-between-operator-and-operatorint%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

An IMO inspired problem

Management

Has there ever been an instance of an active nuclear power plant within or near a war zone?