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.










share|improve this question























  • 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















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.










share|improve this question























  • 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













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.










share|improve this question















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






share|improve this question















share|improve this question













share|improve this question




share|improve this question








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

















  • 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













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;






share|improve this answer





























    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;






    share|improve this answer




















    • Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
      – Aconcagua
      Nov 10 at 9:14











    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',
    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%2f53237408%2ftemplate-parameter-inference-fails%23new-answer', 'question_page');

    );

    Post as a guest















    Required, but never shown

























    2 Answers
    2






    active

    oldest

    votes








    2 Answers
    2






    active

    oldest

    votes









    active

    oldest

    votes






    active

    oldest

    votes








    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;






    share|improve this answer


























      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;






      share|improve this answer
























        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;






        share|improve this answer















        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;







        share|improve this answer














        share|improve this answer



        share|improve this answer








        edited Nov 10 at 12:11

























        answered Nov 10 at 9:06









        songyuanyao

        88.9k11170232




        88.9k11170232






















            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;






            share|improve this answer




















            • Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
              – Aconcagua
              Nov 10 at 9:14















            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;






            share|improve this answer




















            • Alternatively, the lambda can be explicitly cast to function (possible in given case as it has no closure).
              – Aconcagua
              Nov 10 at 9:14













            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;






            share|improve this answer












            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;







            share|improve this answer












            share|improve this answer



            share|improve this answer










            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

















            • 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


















            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%2f53237408%2ftemplate-parameter-inference-fails%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

            Kleinkühnau

            Makov (Slowakei)

            Deutsches Schauspielhaus