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
    21 hours ago















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
    21 hours ago













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 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

















  • 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













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
      21 hours ago











    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






























    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 18 hours ago

























        answered 21 hours ago









        songyuanyao

        87.7k11169231




        87.7k11169231






















            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
              21 hours ago















            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
              21 hours ago













            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 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

















            • 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


















             

            draft saved


            draft discarded















































             


            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














































































            Popular posts from this blog

            Top Tejano songwriter Luis Silva dead of heart attack at 64

            政党

            天津地下鉄3号線