Overload Resolution for inherited functions
Clash Royale CLAN TAG#URR8PPP
up vote
17
down vote
favorite
I want to have a struct that takes an arbitrary number of lambdas and serve as a central calling point for all their call operators.
If the call operator is invoked with an argument list that doesn't match any of the lambdas given on construction, a default call operator should be called.
I thought the following code would accomplish exactly this. The call operator for every lambda is "lifted" into the Poc
class via using
.
template <typename ...Lambdas>
struct Poc : Lambdas...
using Lambdas::operator() ...; //lift the lambda operators into the class
template <typename ...Ts>
auto operator() (Ts...)
std::cout << "general call" << std::endl;
;
//deduction guide
template <typename ...Ts>
Poc(Ts... ts)->Poc<Ts...>;
int main()
auto l_int = (int) std::cout << "int" << std::endl; ;
Poc pocl_int;
poc(1);//calls the default operator. why?
return 0;
When I don't have the default call operator in the struct, everything works as expected (with valid argument lists). If I add it to the struct (as in the code above), the default operator gets called everytime, no matter which arguments I call it with.
In my understanding, the lambda-call-operators and the structs (default)call-operator are present in the same scope. Therefor, they should all be looked at for the overload resolution. Since the lamdba-operator is more specific than the generic default operator, it should be chosen.
Apparently that is not the case. Why is that?
I tested on MSVC, clang and gcc (all in their latest versions).
c++ templates inheritance lambda overloading
add a comment |Â
up vote
17
down vote
favorite
I want to have a struct that takes an arbitrary number of lambdas and serve as a central calling point for all their call operators.
If the call operator is invoked with an argument list that doesn't match any of the lambdas given on construction, a default call operator should be called.
I thought the following code would accomplish exactly this. The call operator for every lambda is "lifted" into the Poc
class via using
.
template <typename ...Lambdas>
struct Poc : Lambdas...
using Lambdas::operator() ...; //lift the lambda operators into the class
template <typename ...Ts>
auto operator() (Ts...)
std::cout << "general call" << std::endl;
;
//deduction guide
template <typename ...Ts>
Poc(Ts... ts)->Poc<Ts...>;
int main()
auto l_int = (int) std::cout << "int" << std::endl; ;
Poc pocl_int;
poc(1);//calls the default operator. why?
return 0;
When I don't have the default call operator in the struct, everything works as expected (with valid argument lists). If I add it to the struct (as in the code above), the default operator gets called everytime, no matter which arguments I call it with.
In my understanding, the lambda-call-operators and the structs (default)call-operator are present in the same scope. Therefor, they should all be looked at for the overload resolution. Since the lamdba-operator is more specific than the generic default operator, it should be chosen.
Apparently that is not the case. Why is that?
I tested on MSVC, clang and gcc (all in their latest versions).
c++ templates inheritance lambda overloading
2
quite an interesting thing you have there. If you dont mind I will steal the idea (just to have some fun with it ;)
– user463035818
26 mins ago
This is the first instance of variadic CRTP I see :)
– YSC
10 mins ago
add a comment |Â
up vote
17
down vote
favorite
up vote
17
down vote
favorite
I want to have a struct that takes an arbitrary number of lambdas and serve as a central calling point for all their call operators.
If the call operator is invoked with an argument list that doesn't match any of the lambdas given on construction, a default call operator should be called.
I thought the following code would accomplish exactly this. The call operator for every lambda is "lifted" into the Poc
class via using
.
template <typename ...Lambdas>
struct Poc : Lambdas...
using Lambdas::operator() ...; //lift the lambda operators into the class
template <typename ...Ts>
auto operator() (Ts...)
std::cout << "general call" << std::endl;
;
//deduction guide
template <typename ...Ts>
Poc(Ts... ts)->Poc<Ts...>;
int main()
auto l_int = (int) std::cout << "int" << std::endl; ;
Poc pocl_int;
poc(1);//calls the default operator. why?
return 0;
When I don't have the default call operator in the struct, everything works as expected (with valid argument lists). If I add it to the struct (as in the code above), the default operator gets called everytime, no matter which arguments I call it with.
In my understanding, the lambda-call-operators and the structs (default)call-operator are present in the same scope. Therefor, they should all be looked at for the overload resolution. Since the lamdba-operator is more specific than the generic default operator, it should be chosen.
Apparently that is not the case. Why is that?
I tested on MSVC, clang and gcc (all in their latest versions).
c++ templates inheritance lambda overloading
I want to have a struct that takes an arbitrary number of lambdas and serve as a central calling point for all their call operators.
If the call operator is invoked with an argument list that doesn't match any of the lambdas given on construction, a default call operator should be called.
I thought the following code would accomplish exactly this. The call operator for every lambda is "lifted" into the Poc
class via using
.
template <typename ...Lambdas>
struct Poc : Lambdas...
using Lambdas::operator() ...; //lift the lambda operators into the class
template <typename ...Ts>
auto operator() (Ts...)
std::cout << "general call" << std::endl;
;
//deduction guide
template <typename ...Ts>
Poc(Ts... ts)->Poc<Ts...>;
int main()
auto l_int = (int) std::cout << "int" << std::endl; ;
Poc pocl_int;
poc(1);//calls the default operator. why?
return 0;
When I don't have the default call operator in the struct, everything works as expected (with valid argument lists). If I add it to the struct (as in the code above), the default operator gets called everytime, no matter which arguments I call it with.
In my understanding, the lambda-call-operators and the structs (default)call-operator are present in the same scope. Therefor, they should all be looked at for the overload resolution. Since the lamdba-operator is more specific than the generic default operator, it should be chosen.
Apparently that is not the case. Why is that?
I tested on MSVC, clang and gcc (all in their latest versions).
c++ templates inheritance lambda overloading
c++ templates inheritance lambda overloading
edited 26 mins ago


NathanOliver
81.1k15110170
81.1k15110170
asked 33 mins ago
LcdDrm
21718
21718
2
quite an interesting thing you have there. If you dont mind I will steal the idea (just to have some fun with it ;)
– user463035818
26 mins ago
This is the first instance of variadic CRTP I see :)
– YSC
10 mins ago
add a comment |Â
2
quite an interesting thing you have there. If you dont mind I will steal the idea (just to have some fun with it ;)
– user463035818
26 mins ago
This is the first instance of variadic CRTP I see :)
– YSC
10 mins ago
2
2
quite an interesting thing you have there. If you dont mind I will steal the idea (just to have some fun with it ;)
– user463035818
26 mins ago
quite an interesting thing you have there. If you dont mind I will steal the idea (just to have some fun with it ;)
– user463035818
26 mins ago
This is the first instance of variadic CRTP I see :)
– YSC
10 mins ago
This is the first instance of variadic CRTP I see :)
– YSC
10 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
up vote
18
down vote
accepted
Thanks for the MCVE!
It's simple when you spot it: your operator is not const
-qualified, while the lambda's one is (unless you define the lambda as mutable
). Hence, it is a better match for your non-const instance of Poc
.
Just add the missingconst
:
auto operator() (Ts...) const
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
3
Nicely spotted!
– lubgr
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make*this
const
?
– NathanOliver
27 mins ago
2
@NathanOliver yes, this constitutes an implicit conversion ofthis
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)
– Quentin
21 mins ago
3
Just like non-member overload resolution
– Caleth
18 mins ago
add a comment |Â
1 Answer
1
active
oldest
votes
1 Answer
1
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
18
down vote
accepted
Thanks for the MCVE!
It's simple when you spot it: your operator is not const
-qualified, while the lambda's one is (unless you define the lambda as mutable
). Hence, it is a better match for your non-const instance of Poc
.
Just add the missingconst
:
auto operator() (Ts...) const
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
3
Nicely spotted!
– lubgr
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make*this
const
?
– NathanOliver
27 mins ago
2
@NathanOliver yes, this constitutes an implicit conversion ofthis
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)
– Quentin
21 mins ago
3
Just like non-member overload resolution
– Caleth
18 mins ago
add a comment |Â
up vote
18
down vote
accepted
Thanks for the MCVE!
It's simple when you spot it: your operator is not const
-qualified, while the lambda's one is (unless you define the lambda as mutable
). Hence, it is a better match for your non-const instance of Poc
.
Just add the missingconst
:
auto operator() (Ts...) const
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
3
Nicely spotted!
– lubgr
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make*this
const
?
– NathanOliver
27 mins ago
2
@NathanOliver yes, this constitutes an implicit conversion ofthis
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)
– Quentin
21 mins ago
3
Just like non-member overload resolution
– Caleth
18 mins ago
add a comment |Â
up vote
18
down vote
accepted
up vote
18
down vote
accepted
Thanks for the MCVE!
It's simple when you spot it: your operator is not const
-qualified, while the lambda's one is (unless you define the lambda as mutable
). Hence, it is a better match for your non-const instance of Poc
.
Just add the missingconst
:
auto operator() (Ts...) const
Thanks for the MCVE!
It's simple when you spot it: your operator is not const
-qualified, while the lambda's one is (unless you define the lambda as mutable
). Hence, it is a better match for your non-const instance of Poc
.
Just add the missingconst
:
auto operator() (Ts...) const
answered 29 mins ago
Quentin
42.8k575132
42.8k575132
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
3
Nicely spotted!
– lubgr
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make*this
const
?
– NathanOliver
27 mins ago
2
@NathanOliver yes, this constitutes an implicit conversion ofthis
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)
– Quentin
21 mins ago
3
Just like non-member overload resolution
– Caleth
18 mins ago
add a comment |Â
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
3
Nicely spotted!
– lubgr
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make*this
const
?
– NathanOliver
27 mins ago
2
@NathanOliver yes, this constitutes an implicit conversion ofthis
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)
– Quentin
21 mins ago
3
Just like non-member overload resolution
– Caleth
18 mins ago
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
Thanks! I would never have figured that out. I'll accept as an answer once the time limit is over.
– LcdDrm
27 mins ago
3
3
Nicely spotted!
– lubgr
27 mins ago
Nicely spotted!
– lubgr
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make
*this
const
?– NathanOliver
27 mins ago
So in this case const qualification trumps template instantiation, and it will stamp out the template to not make
*this
const
?– NathanOliver
27 mins ago
2
2
@NathanOliver yes, this constitutes an implicit conversion of
this
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)– Quentin
21 mins ago
@NathanOliver yes, this constitutes an implicit conversion of
this
which ranks the non-template operator lower. Pardon me if I don't go spelunking through the overload resolution standardese and keep my "just qualify everything equally and all'll be good" stance ;)– Quentin
21 mins ago
3
3
Just like non-member overload resolution
– Caleth
18 mins ago
Just like non-member overload resolution
– Caleth
18 mins ago
add a comment |Â
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
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f53173336%2foverload-resolution-for-inherited-functions%23new-answer', 'question_page');
);
Post as a guest
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
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
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
2
quite an interesting thing you have there. If you dont mind I will steal the idea (just to have some fun with it ;)
– user463035818
26 mins ago
This is the first instance of variadic CRTP I see :)
– YSC
10 mins ago