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
21 hours ago
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 18 hours ago
songyuanyao
87.7k11169231
87.7k11169231
asked 21 hours ago
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
21 hours ago
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
21 hours ago
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
21 hours ago
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
21 hours ago
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
21 hours ago
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 18 hours ago
answered 21 hours ago
songyuanyao
87.7k11169231
87.7k11169231
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
21 hours ago
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
21 hours ago
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 21 hours ago
perreal
70.9k9108137
70.9k9108137
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
21 hours ago
add a comment |
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
21 hours ago
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
21 hours ago
Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
– Aconcagua
21 hours 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%2f53237408%2ftemplate-parameter-inference-fails%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
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
21 hours ago