Template parameter inference fails
up vote
1
down vote
favorite
Consider the following code:
template<class T>
vector<T> filter(typename vector<T>::iterator begin,
typename vector<T>::iterator end,
bool (*cond)(T a))
vector<T> vec;
for (typename vector<T>::iterator it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter<int>(vec.begin(), vec.end(), (int a) return a > 5; );
When I remove the type from the invocation of the function filter, the code does not compile, I.e. when writing
filter(vec.begin(), vec.end(), (int a) return a > 5; );
My question is, why? the compiler can deduce the type both from the lambda and from the iterator.
The error I get is:
Error C2784 'std::vector>
filter(vector>::iterator,vector>::iterator,bool
(__cdecl *)(T))': could not deduce template argument for 'bool
(__cdecl *)(T)' from
'main::' example c:usersdaniidocumentsvisual
studio 2017projectsexampleexamplesource.cpp 24
I couldn't find details about this problem.
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector). If this is the case, why is it? if not, what is the case? is there any way to fix it?
Another thing I encountered was using the iterator itself as a template, i.e. something like
template <class T, class iter, class cond>
vector<T> filter(iter begin, iter end, cond c)
Is it correct programming? This code looks a bit suspicious to me.
c++ templates template-deduction
add a comment |
up vote
1
down vote
favorite
Consider the following code:
template<class T>
vector<T> filter(typename vector<T>::iterator begin,
typename vector<T>::iterator end,
bool (*cond)(T a))
vector<T> vec;
for (typename vector<T>::iterator it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter<int>(vec.begin(), vec.end(), (int a) return a > 5; );
When I remove the type from the invocation of the function filter, the code does not compile, I.e. when writing
filter(vec.begin(), vec.end(), (int a) return a > 5; );
My question is, why? the compiler can deduce the type both from the lambda and from the iterator.
The error I get is:
Error C2784 'std::vector>
filter(vector>::iterator,vector>::iterator,bool
(__cdecl *)(T))': could not deduce template argument for 'bool
(__cdecl *)(T)' from
'main::' example c:usersdaniidocumentsvisual
studio 2017projectsexampleexamplesource.cpp 24
I couldn't find details about this problem.
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector). If this is the case, why is it? if not, what is the case? is there any way to fix it?
Another thing I encountered was using the iterator itself as a template, i.e. something like
template <class T, class iter, class cond>
vector<T> filter(iter begin, iter end, cond c)
Is it correct programming? This code looks a bit suspicious to me.
c++ templates template-deduction
The iterator approach for templates is fine - has nother great advantage: you can use your functions with other containers as well, e. g. std::list, std::deque, ... Having the condition as template as well provides further flexibility; not all lambdas can be converted to functions (if closure is not empty), and it fits for classic (pre-C++11) functors, too.
– Aconcagua
Nov 10 at 9:07
add a comment |
up vote
1
down vote
favorite
up vote
1
down vote
favorite
Consider the following code:
template<class T>
vector<T> filter(typename vector<T>::iterator begin,
typename vector<T>::iterator end,
bool (*cond)(T a))
vector<T> vec;
for (typename vector<T>::iterator it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter<int>(vec.begin(), vec.end(), (int a) return a > 5; );
When I remove the type from the invocation of the function filter, the code does not compile, I.e. when writing
filter(vec.begin(), vec.end(), (int a) return a > 5; );
My question is, why? the compiler can deduce the type both from the lambda and from the iterator.
The error I get is:
Error C2784 'std::vector>
filter(vector>::iterator,vector>::iterator,bool
(__cdecl *)(T))': could not deduce template argument for 'bool
(__cdecl *)(T)' from
'main::' example c:usersdaniidocumentsvisual
studio 2017projectsexampleexamplesource.cpp 24
I couldn't find details about this problem.
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector). If this is the case, why is it? if not, what is the case? is there any way to fix it?
Another thing I encountered was using the iterator itself as a template, i.e. something like
template <class T, class iter, class cond>
vector<T> filter(iter begin, iter end, cond c)
Is it correct programming? This code looks a bit suspicious to me.
c++ templates template-deduction
Consider the following code:
template<class T>
vector<T> filter(typename vector<T>::iterator begin,
typename vector<T>::iterator end,
bool (*cond)(T a))
vector<T> vec;
for (typename vector<T>::iterator it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter<int>(vec.begin(), vec.end(), (int a) return a > 5; );
When I remove the type from the invocation of the function filter, the code does not compile, I.e. when writing
filter(vec.begin(), vec.end(), (int a) return a > 5; );
My question is, why? the compiler can deduce the type both from the lambda and from the iterator.
The error I get is:
Error C2784 'std::vector>
filter(vector>::iterator,vector>::iterator,bool
(__cdecl *)(T))': could not deduce template argument for 'bool
(__cdecl *)(T)' from
'main::' example c:usersdaniidocumentsvisual
studio 2017projectsexampleexamplesource.cpp 24
I couldn't find details about this problem.
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector). If this is the case, why is it? if not, what is the case? is there any way to fix it?
Another thing I encountered was using the iterator itself as a template, i.e. something like
template <class T, class iter, class cond>
vector<T> filter(iter begin, iter end, cond c)
Is it correct programming? This code looks a bit suspicious to me.
c++ templates template-deduction
c++ templates template-deduction
edited Nov 10 at 12:11
songyuanyao
88.9k11170232
88.9k11170232
asked Nov 10 at 8:52
user3529428
83
83
The iterator approach for templates is fine - has nother great advantage: you can use your functions with other containers as well, e. g. std::list, std::deque, ... Having the condition as template as well provides further flexibility; not all lambdas can be converted to functions (if closure is not empty), and it fits for classic (pre-C++11) functors, too.
– Aconcagua
Nov 10 at 9:07
add a comment |
The iterator approach for templates is fine - has nother great advantage: you can use your functions with other containers as well, e. g. std::list, std::deque, ... Having the condition as template as well provides further flexibility; not all lambdas can be converted to functions (if closure is not empty), and it fits for classic (pre-C++11) functors, too.
– Aconcagua
Nov 10 at 9:07
The iterator approach for templates is fine - has nother great advantage: you can use your functions with other containers as well, e. g. std::list, std::deque, ... Having the condition as template as well provides further flexibility; not all lambdas can be converted to functions (if closure is not empty), and it fits for classic (pre-C++11) functors, too.
– Aconcagua
Nov 10 at 9:07
The iterator approach for templates is fine - has nother great advantage: you can use your functions with other containers as well, e. g. std::list, std::deque, ... Having the condition as template as well provides further flexibility; not all lambdas can be converted to functions (if closure is not empty), and it fits for classic (pre-C++11) functors, too.
– Aconcagua
Nov 10 at 9:07
add a comment |
2 Answers
2
active
oldest
votes
up vote
1
down vote
accepted
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector).
Yes. This belongs to non-deduced contexts:
In the following cases, the types, templates, and non-type values that
are used to compose P do not participate in template argument
deduction, but instead use the template arguments that were either
deduced elsewhere or explicitly specified. If a template parameter is
used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.
1) The nested-name-specifier (everything to the left of the scope
resolution operator ::) of a type that was specified using a
qualified-id:
Note that lambda expression without capture (the 3rd argument) could convert to function pointer implicitly, but template argument deduction doesn't consider implicit conversions.
Type deduction does not consider implicit conversions (other than type
adjustments listed above): that's the job for overload resolution,
which happens later.
Then, type deduction fails here.
Your idea for fixing is good idea but you don't need the template parameter T, which can't (and don't need to) be deduced. You can change it to:
template<class iter, class cond>
auto filter(iter begin, iter end, cond c)
vector<typename std::iterator_traits<iter>::value_type> vec;
for (auto it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
add a comment |
up vote
2
down vote
It is because the lambda type is not exactly the function type that is expected so the template deduction won't work. The compiler can't do implicit conversion and template deduction at the same time. It will if you use a function:
bool f(int a)
return a > 5;
int main()
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter(vec.begin(), vec.end(), f);
return 0;
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
add a comment |
2 Answers
2
active
oldest
votes
2 Answers
2
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
1
down vote
accepted
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector).
Yes. This belongs to non-deduced contexts:
In the following cases, the types, templates, and non-type values that
are used to compose P do not participate in template argument
deduction, but instead use the template arguments that were either
deduced elsewhere or explicitly specified. If a template parameter is
used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.
1) The nested-name-specifier (everything to the left of the scope
resolution operator ::) of a type that was specified using a
qualified-id:
Note that lambda expression without capture (the 3rd argument) could convert to function pointer implicitly, but template argument deduction doesn't consider implicit conversions.
Type deduction does not consider implicit conversions (other than type
adjustments listed above): that's the job for overload resolution,
which happens later.
Then, type deduction fails here.
Your idea for fixing is good idea but you don't need the template parameter T, which can't (and don't need to) be deduced. You can change it to:
template<class iter, class cond>
auto filter(iter begin, iter end, cond c)
vector<typename std::iterator_traits<iter>::value_type> vec;
for (auto it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
add a comment |
up vote
1
down vote
accepted
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector).
Yes. This belongs to non-deduced contexts:
In the following cases, the types, templates, and non-type values that
are used to compose P do not participate in template argument
deduction, but instead use the template arguments that were either
deduced elsewhere or explicitly specified. If a template parameter is
used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.
1) The nested-name-specifier (everything to the left of the scope
resolution operator ::) of a type that was specified using a
qualified-id:
Note that lambda expression without capture (the 3rd argument) could convert to function pointer implicitly, but template argument deduction doesn't consider implicit conversions.
Type deduction does not consider implicit conversions (other than type
adjustments listed above): that's the job for overload resolution,
which happens later.
Then, type deduction fails here.
Your idea for fixing is good idea but you don't need the template parameter T, which can't (and don't need to) be deduced. You can change it to:
template<class iter, class cond>
auto filter(iter begin, iter end, cond c)
vector<typename std::iterator_traits<iter>::value_type> vec;
for (auto it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
add a comment |
up vote
1
down vote
accepted
up vote
1
down vote
accepted
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector).
Yes. This belongs to non-deduced contexts:
In the following cases, the types, templates, and non-type values that
are used to compose P do not participate in template argument
deduction, but instead use the template arguments that were either
deduced elsewhere or explicitly specified. If a template parameter is
used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.
1) The nested-name-specifier (everything to the left of the scope
resolution operator ::) of a type that was specified using a
qualified-id:
Note that lambda expression without capture (the 3rd argument) could convert to function pointer implicitly, but template argument deduction doesn't consider implicit conversions.
Type deduction does not consider implicit conversions (other than type
adjustments listed above): that's the job for overload resolution,
which happens later.
Then, type deduction fails here.
Your idea for fixing is good idea but you don't need the template parameter T, which can't (and don't need to) be deduced. You can change it to:
template<class iter, class cond>
auto filter(iter begin, iter end, cond c)
vector<typename std::iterator_traits<iter>::value_type> vec;
for (auto it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
My guess is, the compiler can't deduce inner types? (e.g can't deduce int from vector).
Yes. This belongs to non-deduced contexts:
In the following cases, the types, templates, and non-type values that
are used to compose P do not participate in template argument
deduction, but instead use the template arguments that were either
deduced elsewhere or explicitly specified. If a template parameter is
used only in non-deduced contexts and is not explicitly specified,
template argument deduction fails.
1) The nested-name-specifier (everything to the left of the scope
resolution operator ::) of a type that was specified using a
qualified-id:
Note that lambda expression without capture (the 3rd argument) could convert to function pointer implicitly, but template argument deduction doesn't consider implicit conversions.
Type deduction does not consider implicit conversions (other than type
adjustments listed above): that's the job for overload resolution,
which happens later.
Then, type deduction fails here.
Your idea for fixing is good idea but you don't need the template parameter T, which can't (and don't need to) be deduced. You can change it to:
template<class iter, class cond>
auto filter(iter begin, iter end, cond c)
vector<typename std::iterator_traits<iter>::value_type> vec;
for (auto it = begin; it != end; it++)
if (cond(*it))
vec.push_back(*it);
return vec;
edited Nov 10 at 12:11
answered Nov 10 at 9:06
songyuanyao
88.9k11170232
88.9k11170232
add a comment |
add a comment |
up vote
2
down vote
It is because the lambda type is not exactly the function type that is expected so the template deduction won't work. The compiler can't do implicit conversion and template deduction at the same time. It will if you use a function:
bool f(int a)
return a > 5;
int main()
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter(vec.begin(), vec.end(), f);
return 0;
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
add a comment |
up vote
2
down vote
It is because the lambda type is not exactly the function type that is expected so the template deduction won't work. The compiler can't do implicit conversion and template deduction at the same time. It will if you use a function:
bool f(int a)
return a > 5;
int main()
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter(vec.begin(), vec.end(), f);
return 0;
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
add a comment |
up vote
2
down vote
up vote
2
down vote
It is because the lambda type is not exactly the function type that is expected so the template deduction won't work. The compiler can't do implicit conversion and template deduction at the same time. It will if you use a function:
bool f(int a)
return a > 5;
int main()
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter(vec.begin(), vec.end(), f);
return 0;
It is because the lambda type is not exactly the function type that is expected so the template deduction won't work. The compiler can't do implicit conversion and template deduction at the same time. It will if you use a function:
bool f(int a)
return a > 5;
int main()
vector<int> vec = 1,2,3,4,5,6,7,8,9,10 ;
auto another_vec = filter(vec.begin(), vec.end(), f);
return 0;
answered Nov 10 at 9:08
perreal
71.4k9110137
71.4k9110137
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
add a comment |
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
Nov 10 at 9:14
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.
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.
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%2f53237408%2ftemplate-parameter-inference-fails%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
The iterator approach for templates is fine - has nother great advantage: you can use your functions with other containers as well, e. g. std::list, std::deque, ... Having the condition as template as well provides further flexibility; not all lambdas can be converted to functions (if closure is not empty), and it fits for classic (pre-C++11) functors, too.
– Aconcagua
Nov 10 at 9:07