Variadic Template Functions: No matching function for call, std::endl

The name of the pictureThe name of the pictureThe name of the pictureClash Royale CLAN TAG#URR8PPP











up vote
7
down vote

favorite












In my code, I use variadic template functions for the logging purpose. But when I use std::endl as parameter, I get the following compiler error:




Error: no matching function for call to 'LOG_ERROR(const char [14],
int&, )' LOG_ERROR("Sum of x+y
= ", z, std::endl);



note: candidate: 'void LOG_ERROR()' inline void LOG_ERROR() {



note: candidate expects 0 arguments, 3 provided




My Code:



#include <iostream>

inline void LOG_ERROR()
std::cout << std::endl;


template<typename First, typename ...Rest>
void LOG_ERROR(First && first, Rest && ...rest)
std::cout << std::forward<First>(first);
LOG_ERROR(std::forward<Rest>(rest)...);


int main()
int foo=40;
LOG_ERROR("My foo = ", foo, std::endl);



The code works fine with "n" but I would love to learn why it fails with std::endl and how I can fix it







share|improve this question


















  • 2




    The issue is also discussed here. I don't think it's a duplicate though, as your question involves passing std::endl in parameter pack to be expanded?!
    – lubgr
    Aug 16 at 7:10







  • 3




    std::endl is a function template, not just a function. You're passing it without deduction (either specific or deduced). If you populated the template to an actual function instantiation (such as std::endl<char, std::char_traits<char>>, it should work.
    – WhozCraig
    Aug 16 at 7:14











  • @WhozCraig The thing here is I won't be the user of the LOG_ERROR function but I would like the user to be able to use the function with std::endl.
    – eneski
    Aug 16 at 7:25






  • 1




    @eneski I understand, but I don't know what to tell you. The problem is the context in which it is used. There is no "there" there until such time as std::endl is used in a deducible context, which it isn't in your case.
    – WhozCraig
    Aug 16 at 7:36














up vote
7
down vote

favorite












In my code, I use variadic template functions for the logging purpose. But when I use std::endl as parameter, I get the following compiler error:




Error: no matching function for call to 'LOG_ERROR(const char [14],
int&, )' LOG_ERROR("Sum of x+y
= ", z, std::endl);



note: candidate: 'void LOG_ERROR()' inline void LOG_ERROR() {



note: candidate expects 0 arguments, 3 provided




My Code:



#include <iostream>

inline void LOG_ERROR()
std::cout << std::endl;


template<typename First, typename ...Rest>
void LOG_ERROR(First && first, Rest && ...rest)
std::cout << std::forward<First>(first);
LOG_ERROR(std::forward<Rest>(rest)...);


int main()
int foo=40;
LOG_ERROR("My foo = ", foo, std::endl);



The code works fine with "n" but I would love to learn why it fails with std::endl and how I can fix it







share|improve this question


















  • 2




    The issue is also discussed here. I don't think it's a duplicate though, as your question involves passing std::endl in parameter pack to be expanded?!
    – lubgr
    Aug 16 at 7:10







  • 3




    std::endl is a function template, not just a function. You're passing it without deduction (either specific or deduced). If you populated the template to an actual function instantiation (such as std::endl<char, std::char_traits<char>>, it should work.
    – WhozCraig
    Aug 16 at 7:14











  • @WhozCraig The thing here is I won't be the user of the LOG_ERROR function but I would like the user to be able to use the function with std::endl.
    – eneski
    Aug 16 at 7:25






  • 1




    @eneski I understand, but I don't know what to tell you. The problem is the context in which it is used. There is no "there" there until such time as std::endl is used in a deducible context, which it isn't in your case.
    – WhozCraig
    Aug 16 at 7:36












up vote
7
down vote

favorite









up vote
7
down vote

favorite











In my code, I use variadic template functions for the logging purpose. But when I use std::endl as parameter, I get the following compiler error:




Error: no matching function for call to 'LOG_ERROR(const char [14],
int&, )' LOG_ERROR("Sum of x+y
= ", z, std::endl);



note: candidate: 'void LOG_ERROR()' inline void LOG_ERROR() {



note: candidate expects 0 arguments, 3 provided




My Code:



#include <iostream>

inline void LOG_ERROR()
std::cout << std::endl;


template<typename First, typename ...Rest>
void LOG_ERROR(First && first, Rest && ...rest)
std::cout << std::forward<First>(first);
LOG_ERROR(std::forward<Rest>(rest)...);


int main()
int foo=40;
LOG_ERROR("My foo = ", foo, std::endl);



The code works fine with "n" but I would love to learn why it fails with std::endl and how I can fix it







share|improve this question














In my code, I use variadic template functions for the logging purpose. But when I use std::endl as parameter, I get the following compiler error:




Error: no matching function for call to 'LOG_ERROR(const char [14],
int&, )' LOG_ERROR("Sum of x+y
= ", z, std::endl);



note: candidate: 'void LOG_ERROR()' inline void LOG_ERROR() {



note: candidate expects 0 arguments, 3 provided




My Code:



#include <iostream>

inline void LOG_ERROR()
std::cout << std::endl;


template<typename First, typename ...Rest>
void LOG_ERROR(First && first, Rest && ...rest)
std::cout << std::forward<First>(first);
LOG_ERROR(std::forward<Rest>(rest)...);


int main()
int foo=40;
LOG_ERROR("My foo = ", foo, std::endl);



The code works fine with "n" but I would love to learn why it fails with std::endl and how I can fix it









share|improve this question













share|improve this question




share|improve this question








edited Aug 16 at 8:01

























asked Aug 16 at 7:04









eneski

653520




653520







  • 2




    The issue is also discussed here. I don't think it's a duplicate though, as your question involves passing std::endl in parameter pack to be expanded?!
    – lubgr
    Aug 16 at 7:10







  • 3




    std::endl is a function template, not just a function. You're passing it without deduction (either specific or deduced). If you populated the template to an actual function instantiation (such as std::endl<char, std::char_traits<char>>, it should work.
    – WhozCraig
    Aug 16 at 7:14











  • @WhozCraig The thing here is I won't be the user of the LOG_ERROR function but I would like the user to be able to use the function with std::endl.
    – eneski
    Aug 16 at 7:25






  • 1




    @eneski I understand, but I don't know what to tell you. The problem is the context in which it is used. There is no "there" there until such time as std::endl is used in a deducible context, which it isn't in your case.
    – WhozCraig
    Aug 16 at 7:36












  • 2




    The issue is also discussed here. I don't think it's a duplicate though, as your question involves passing std::endl in parameter pack to be expanded?!
    – lubgr
    Aug 16 at 7:10







  • 3




    std::endl is a function template, not just a function. You're passing it without deduction (either specific or deduced). If you populated the template to an actual function instantiation (such as std::endl<char, std::char_traits<char>>, it should work.
    – WhozCraig
    Aug 16 at 7:14











  • @WhozCraig The thing here is I won't be the user of the LOG_ERROR function but I would like the user to be able to use the function with std::endl.
    – eneski
    Aug 16 at 7:25






  • 1




    @eneski I understand, but I don't know what to tell you. The problem is the context in which it is used. There is no "there" there until such time as std::endl is used in a deducible context, which it isn't in your case.
    – WhozCraig
    Aug 16 at 7:36







2




2




The issue is also discussed here. I don't think it's a duplicate though, as your question involves passing std::endl in parameter pack to be expanded?!
– lubgr
Aug 16 at 7:10





The issue is also discussed here. I don't think it's a duplicate though, as your question involves passing std::endl in parameter pack to be expanded?!
– lubgr
Aug 16 at 7:10





3




3




std::endl is a function template, not just a function. You're passing it without deduction (either specific or deduced). If you populated the template to an actual function instantiation (such as std::endl<char, std::char_traits<char>>, it should work.
– WhozCraig
Aug 16 at 7:14





std::endl is a function template, not just a function. You're passing it without deduction (either specific or deduced). If you populated the template to an actual function instantiation (such as std::endl<char, std::char_traits<char>>, it should work.
– WhozCraig
Aug 16 at 7:14













@WhozCraig The thing here is I won't be the user of the LOG_ERROR function but I would like the user to be able to use the function with std::endl.
– eneski
Aug 16 at 7:25




@WhozCraig The thing here is I won't be the user of the LOG_ERROR function but I would like the user to be able to use the function with std::endl.
– eneski
Aug 16 at 7:25




1




1




@eneski I understand, but I don't know what to tell you. The problem is the context in which it is used. There is no "there" there until such time as std::endl is used in a deducible context, which it isn't in your case.
– WhozCraig
Aug 16 at 7:36




@eneski I understand, but I don't know what to tell you. The problem is the context in which it is used. There is no "there" there until such time as std::endl is used in a deducible context, which it isn't in your case.
– WhozCraig
Aug 16 at 7:36












4 Answers
4






active

oldest

votes

















up vote
1
down vote



accepted










std::endl is not a character type or any other type. It is output stream manipulator. Its return type is output stream.



So, you can not pass it without typecasting. Please look here






share|improve this answer





























    up vote
    8
    down vote













    Long story short - std::endl is function template which template arguments can't be deduced while passing. You can help Your compiler this way:



    LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);


    As much as I feel this is ugly piece of code it works perfectly.






    share|improve this answer




















    • auto endl = std::endl<char, std::char_traits<char>>; helps.
      – YSC
      Aug 16 at 13:11











    • @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
      – bartop
      Aug 16 at 13:13










    • Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
      – Barry
      Aug 16 at 13:25











    • @Barry Good to know. Thank you.
      – YSC
      Aug 16 at 13:36










    • @Barry Could You reference to standard? I never heard of such a restriction
      – bartop
      Aug 16 at 18:55


















    up vote
    7
    down vote













    Until someone comes with a better solution, you can use a trivial wrapper with an appropriate operator overload:



    struct EndlWrap ;

    std::ostream& operator << (std::ostream& os, EndlWrap)
    return os << std::endl;



    which should be usable like this:



    LOG_ERROR("My foo = ", foo, EndlWrap);


    This has an advantage when your logging destination might be a non-standard stream, i.e., the template arguments of std::endl can still be deduced when it's <<'d into the stream.






    share|improve this answer


















    • 4




      Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
      – Jarod42
      Aug 16 at 7:30











    • That's nice!! The question is tagged C++11, though.
      – lubgr
      Aug 16 at 7:32










    • So fallback to old functor class.
      – Jarod42
      Aug 16 at 7:34










    • This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
      – lubgr
      Aug 16 at 7:36






    • 1




      But then cannot be used with std::wcout...
      – Jarod42
      Aug 16 at 7:40

















    up vote
    1
    down vote













    You can use defaulted template parameters and defaulted function arguments instead of a variadic template.



    The code is less clean and you will have to choose a limitation on the number of parameters, but it will do the job:



    template<class...>
    inline void LOG_ERROR_();
    template<>
    inline void LOG_ERROR_<>()
    std::cout << std::endl;

    template<typename First, typename ... Rest>
    void LOG_ERROR_(First && first, Rest && ...rest)
    std::cout << std::forward<First>(first);
    LOG_ERROR_<Rest...>(std::forward<Rest>(rest)...);
    //could be cleaner with if constexpr


    using manip_t = std::basic_ostream<char>&(*)(std::basic_ostream<char>&);

    std::basic_ostream<char>& no_manip(std::basic_ostream<char>& o)
    return o;


    template<typename A=manip_t
    ,typename B=manip_t, typename C= manip_t
    ,typename D=manip_t // to be continued
    >
    inline void LOG_ERROR(A&& a=no_manip, B&& b=no_manip,C&& c=no_manip
    ,D&& d=no_manip /*to be continued*/)
    LOG_ERROR_<A,B,C,D/*to be continued*/>(
    std::forward<A>(a),std::forward<B>(b),std::forward<C>(c),
    std::forward<D>(d)/*to be continued*/);



    Depending on the compiler this code could produce ugly assembly. One solution is to write an overload for each possible number of argument, or have a good knowldge of compiler specific function attributes (always_inline,etc...)






    share|improve this answer






















      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: false,
      showLowRepImageUploadWarning: true,
      reputationToPostImages: 10,
      bindNavPrevention: true,
      postfix: "",
      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%2f51871383%2fvariadic-template-functions-no-matching-function-for-call-stdendl%23new-answer', 'question_page');

      );

      Post as a guest






























      4 Answers
      4






      active

      oldest

      votes








      4 Answers
      4






      active

      oldest

      votes









      active

      oldest

      votes






      active

      oldest

      votes








      up vote
      1
      down vote



      accepted










      std::endl is not a character type or any other type. It is output stream manipulator. Its return type is output stream.



      So, you can not pass it without typecasting. Please look here






      share|improve this answer


























        up vote
        1
        down vote



        accepted










        std::endl is not a character type or any other type. It is output stream manipulator. Its return type is output stream.



        So, you can not pass it without typecasting. Please look here






        share|improve this answer
























          up vote
          1
          down vote



          accepted







          up vote
          1
          down vote



          accepted






          std::endl is not a character type or any other type. It is output stream manipulator. Its return type is output stream.



          So, you can not pass it without typecasting. Please look here






          share|improve this answer














          std::endl is not a character type or any other type. It is output stream manipulator. Its return type is output stream.



          So, you can not pass it without typecasting. Please look here







          share|improve this answer














          share|improve this answer



          share|improve this answer








          edited Aug 23 at 12:03









          eneski

          653520




          653520










          answered Aug 16 at 7:22









          user2641018

          805




          805






















              up vote
              8
              down vote













              Long story short - std::endl is function template which template arguments can't be deduced while passing. You can help Your compiler this way:



              LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);


              As much as I feel this is ugly piece of code it works perfectly.






              share|improve this answer




















              • auto endl = std::endl<char, std::char_traits<char>>; helps.
                – YSC
                Aug 16 at 13:11











              • @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
                – bartop
                Aug 16 at 13:13










              • Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
                – Barry
                Aug 16 at 13:25











              • @Barry Good to know. Thank you.
                – YSC
                Aug 16 at 13:36










              • @Barry Could You reference to standard? I never heard of such a restriction
                – bartop
                Aug 16 at 18:55















              up vote
              8
              down vote













              Long story short - std::endl is function template which template arguments can't be deduced while passing. You can help Your compiler this way:



              LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);


              As much as I feel this is ugly piece of code it works perfectly.






              share|improve this answer




















              • auto endl = std::endl<char, std::char_traits<char>>; helps.
                – YSC
                Aug 16 at 13:11











              • @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
                – bartop
                Aug 16 at 13:13










              • Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
                – Barry
                Aug 16 at 13:25











              • @Barry Good to know. Thank you.
                – YSC
                Aug 16 at 13:36










              • @Barry Could You reference to standard? I never heard of such a restriction
                – bartop
                Aug 16 at 18:55













              up vote
              8
              down vote










              up vote
              8
              down vote









              Long story short - std::endl is function template which template arguments can't be deduced while passing. You can help Your compiler this way:



              LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);


              As much as I feel this is ugly piece of code it works perfectly.






              share|improve this answer












              Long story short - std::endl is function template which template arguments can't be deduced while passing. You can help Your compiler this way:



              LOG_ERROR("My foo = ", foo, std::endl<char, std::char_traits<char>>);


              As much as I feel this is ugly piece of code it works perfectly.







              share|improve this answer












              share|improve this answer



              share|improve this answer










              answered Aug 16 at 7:19









              bartop

              2,153823




              2,153823











              • auto endl = std::endl<char, std::char_traits<char>>; helps.
                – YSC
                Aug 16 at 13:11











              • @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
                – bartop
                Aug 16 at 13:13










              • Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
                – Barry
                Aug 16 at 13:25











              • @Barry Good to know. Thank you.
                – YSC
                Aug 16 at 13:36










              • @Barry Could You reference to standard? I never heard of such a restriction
                – bartop
                Aug 16 at 18:55

















              • auto endl = std::endl<char, std::char_traits<char>>; helps.
                – YSC
                Aug 16 at 13:11











              • @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
                – bartop
                Aug 16 at 13:13










              • Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
                – Barry
                Aug 16 at 13:25











              • @Barry Good to know. Thank you.
                – YSC
                Aug 16 at 13:36










              • @Barry Could You reference to standard? I never heard of such a restriction
                – bartop
                Aug 16 at 18:55
















              auto endl = std::endl<char, std::char_traits<char>>; helps.
              – YSC
              Aug 16 at 13:11





              auto endl = std::endl<char, std::char_traits<char>>; helps.
              – YSC
              Aug 16 at 13:11













              @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
              – bartop
              Aug 16 at 13:13




              @YSC If I were to choose, I'd go with suggested somwhere down here: auto endl = (auto&&os) -> decltype(auto) return os << std::endl;
              – bartop
              Aug 16 at 13:13












              Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
              – Barry
              Aug 16 at 13:25





              Don't do this. It doesn't "work perfectly" - it's unspecified. The standard library reserves the right to break this code at any time - you should not take the address of or explicitly specify standard library functions/function templates. You have to use a lambda (or normal function object).
              – Barry
              Aug 16 at 13:25













              @Barry Good to know. Thank you.
              – YSC
              Aug 16 at 13:36




              @Barry Good to know. Thank you.
              – YSC
              Aug 16 at 13:36












              @Barry Could You reference to standard? I never heard of such a restriction
              – bartop
              Aug 16 at 18:55





              @Barry Could You reference to standard? I never heard of such a restriction
              – bartop
              Aug 16 at 18:55











              up vote
              7
              down vote













              Until someone comes with a better solution, you can use a trivial wrapper with an appropriate operator overload:



              struct EndlWrap ;

              std::ostream& operator << (std::ostream& os, EndlWrap)
              return os << std::endl;



              which should be usable like this:



              LOG_ERROR("My foo = ", foo, EndlWrap);


              This has an advantage when your logging destination might be a non-standard stream, i.e., the template arguments of std::endl can still be deduced when it's <<'d into the stream.






              share|improve this answer


















              • 4




                Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
                – Jarod42
                Aug 16 at 7:30











              • That's nice!! The question is tagged C++11, though.
                – lubgr
                Aug 16 at 7:32










              • So fallback to old functor class.
                – Jarod42
                Aug 16 at 7:34










              • This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
                – lubgr
                Aug 16 at 7:36






              • 1




                But then cannot be used with std::wcout...
                – Jarod42
                Aug 16 at 7:40














              up vote
              7
              down vote













              Until someone comes with a better solution, you can use a trivial wrapper with an appropriate operator overload:



              struct EndlWrap ;

              std::ostream& operator << (std::ostream& os, EndlWrap)
              return os << std::endl;



              which should be usable like this:



              LOG_ERROR("My foo = ", foo, EndlWrap);


              This has an advantage when your logging destination might be a non-standard stream, i.e., the template arguments of std::endl can still be deduced when it's <<'d into the stream.






              share|improve this answer


















              • 4




                Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
                – Jarod42
                Aug 16 at 7:30











              • That's nice!! The question is tagged C++11, though.
                – lubgr
                Aug 16 at 7:32










              • So fallback to old functor class.
                – Jarod42
                Aug 16 at 7:34










              • This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
                – lubgr
                Aug 16 at 7:36






              • 1




                But then cannot be used with std::wcout...
                – Jarod42
                Aug 16 at 7:40












              up vote
              7
              down vote










              up vote
              7
              down vote









              Until someone comes with a better solution, you can use a trivial wrapper with an appropriate operator overload:



              struct EndlWrap ;

              std::ostream& operator << (std::ostream& os, EndlWrap)
              return os << std::endl;



              which should be usable like this:



              LOG_ERROR("My foo = ", foo, EndlWrap);


              This has an advantage when your logging destination might be a non-standard stream, i.e., the template arguments of std::endl can still be deduced when it's <<'d into the stream.






              share|improve this answer














              Until someone comes with a better solution, you can use a trivial wrapper with an appropriate operator overload:



              struct EndlWrap ;

              std::ostream& operator << (std::ostream& os, EndlWrap)
              return os << std::endl;



              which should be usable like this:



              LOG_ERROR("My foo = ", foo, EndlWrap);


              This has an advantage when your logging destination might be a non-standard stream, i.e., the template arguments of std::endl can still be deduced when it's <<'d into the stream.







              share|improve this answer














              share|improve this answer



              share|improve this answer








              edited Aug 16 at 7:24

























              answered Aug 16 at 7:16









              lubgr

              5,3761136




              5,3761136







              • 4




                Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
                – Jarod42
                Aug 16 at 7:30











              • That's nice!! The question is tagged C++11, though.
                – lubgr
                Aug 16 at 7:32










              • So fallback to old functor class.
                – Jarod42
                Aug 16 at 7:34










              • This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
                – lubgr
                Aug 16 at 7:36






              • 1




                But then cannot be used with std::wcout...
                – Jarod42
                Aug 16 at 7:40












              • 4




                Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
                – Jarod42
                Aug 16 at 7:30











              • That's nice!! The question is tagged C++11, though.
                – lubgr
                Aug 16 at 7:32










              • So fallback to old functor class.
                – Jarod42
                Aug 16 at 7:34










              • This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
                – lubgr
                Aug 16 at 7:36






              • 1




                But then cannot be used with std::wcout...
                – Jarod42
                Aug 16 at 7:40







              4




              4




              Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
              – Jarod42
              Aug 16 at 7:30





              Possibly: auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl; . it works also with std::wcout. (or templatize your function).
              – Jarod42
              Aug 16 at 7:30













              That's nice!! The question is tagged C++11, though.
              – lubgr
              Aug 16 at 7:32




              That's nice!! The question is tagged C++11, though.
              – lubgr
              Aug 16 at 7:32












              So fallback to old functor class.
              – Jarod42
              Aug 16 at 7:34




              So fallback to old functor class.
              – Jarod42
              Aug 16 at 7:34












              This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
              – lubgr
              Aug 16 at 7:36




              This would work, too: auto EndlWrap = (std::ostream& os) -> std::ostream& return os << std::endl; ;
              – lubgr
              Aug 16 at 7:36




              1




              1




              But then cannot be used with std::wcout...
              – Jarod42
              Aug 16 at 7:40




              But then cannot be used with std::wcout...
              – Jarod42
              Aug 16 at 7:40










              up vote
              1
              down vote













              You can use defaulted template parameters and defaulted function arguments instead of a variadic template.



              The code is less clean and you will have to choose a limitation on the number of parameters, but it will do the job:



              template<class...>
              inline void LOG_ERROR_();
              template<>
              inline void LOG_ERROR_<>()
              std::cout << std::endl;

              template<typename First, typename ... Rest>
              void LOG_ERROR_(First && first, Rest && ...rest)
              std::cout << std::forward<First>(first);
              LOG_ERROR_<Rest...>(std::forward<Rest>(rest)...);
              //could be cleaner with if constexpr


              using manip_t = std::basic_ostream<char>&(*)(std::basic_ostream<char>&);

              std::basic_ostream<char>& no_manip(std::basic_ostream<char>& o)
              return o;


              template<typename A=manip_t
              ,typename B=manip_t, typename C= manip_t
              ,typename D=manip_t // to be continued
              >
              inline void LOG_ERROR(A&& a=no_manip, B&& b=no_manip,C&& c=no_manip
              ,D&& d=no_manip /*to be continued*/)
              LOG_ERROR_<A,B,C,D/*to be continued*/>(
              std::forward<A>(a),std::forward<B>(b),std::forward<C>(c),
              std::forward<D>(d)/*to be continued*/);



              Depending on the compiler this code could produce ugly assembly. One solution is to write an overload for each possible number of argument, or have a good knowldge of compiler specific function attributes (always_inline,etc...)






              share|improve this answer


























                up vote
                1
                down vote













                You can use defaulted template parameters and defaulted function arguments instead of a variadic template.



                The code is less clean and you will have to choose a limitation on the number of parameters, but it will do the job:



                template<class...>
                inline void LOG_ERROR_();
                template<>
                inline void LOG_ERROR_<>()
                std::cout << std::endl;

                template<typename First, typename ... Rest>
                void LOG_ERROR_(First && first, Rest && ...rest)
                std::cout << std::forward<First>(first);
                LOG_ERROR_<Rest...>(std::forward<Rest>(rest)...);
                //could be cleaner with if constexpr


                using manip_t = std::basic_ostream<char>&(*)(std::basic_ostream<char>&);

                std::basic_ostream<char>& no_manip(std::basic_ostream<char>& o)
                return o;


                template<typename A=manip_t
                ,typename B=manip_t, typename C= manip_t
                ,typename D=manip_t // to be continued
                >
                inline void LOG_ERROR(A&& a=no_manip, B&& b=no_manip,C&& c=no_manip
                ,D&& d=no_manip /*to be continued*/)
                LOG_ERROR_<A,B,C,D/*to be continued*/>(
                std::forward<A>(a),std::forward<B>(b),std::forward<C>(c),
                std::forward<D>(d)/*to be continued*/);



                Depending on the compiler this code could produce ugly assembly. One solution is to write an overload for each possible number of argument, or have a good knowldge of compiler specific function attributes (always_inline,etc...)






                share|improve this answer
























                  up vote
                  1
                  down vote










                  up vote
                  1
                  down vote









                  You can use defaulted template parameters and defaulted function arguments instead of a variadic template.



                  The code is less clean and you will have to choose a limitation on the number of parameters, but it will do the job:



                  template<class...>
                  inline void LOG_ERROR_();
                  template<>
                  inline void LOG_ERROR_<>()
                  std::cout << std::endl;

                  template<typename First, typename ... Rest>
                  void LOG_ERROR_(First && first, Rest && ...rest)
                  std::cout << std::forward<First>(first);
                  LOG_ERROR_<Rest...>(std::forward<Rest>(rest)...);
                  //could be cleaner with if constexpr


                  using manip_t = std::basic_ostream<char>&(*)(std::basic_ostream<char>&);

                  std::basic_ostream<char>& no_manip(std::basic_ostream<char>& o)
                  return o;


                  template<typename A=manip_t
                  ,typename B=manip_t, typename C= manip_t
                  ,typename D=manip_t // to be continued
                  >
                  inline void LOG_ERROR(A&& a=no_manip, B&& b=no_manip,C&& c=no_manip
                  ,D&& d=no_manip /*to be continued*/)
                  LOG_ERROR_<A,B,C,D/*to be continued*/>(
                  std::forward<A>(a),std::forward<B>(b),std::forward<C>(c),
                  std::forward<D>(d)/*to be continued*/);



                  Depending on the compiler this code could produce ugly assembly. One solution is to write an overload for each possible number of argument, or have a good knowldge of compiler specific function attributes (always_inline,etc...)






                  share|improve this answer














                  You can use defaulted template parameters and defaulted function arguments instead of a variadic template.



                  The code is less clean and you will have to choose a limitation on the number of parameters, but it will do the job:



                  template<class...>
                  inline void LOG_ERROR_();
                  template<>
                  inline void LOG_ERROR_<>()
                  std::cout << std::endl;

                  template<typename First, typename ... Rest>
                  void LOG_ERROR_(First && first, Rest && ...rest)
                  std::cout << std::forward<First>(first);
                  LOG_ERROR_<Rest...>(std::forward<Rest>(rest)...);
                  //could be cleaner with if constexpr


                  using manip_t = std::basic_ostream<char>&(*)(std::basic_ostream<char>&);

                  std::basic_ostream<char>& no_manip(std::basic_ostream<char>& o)
                  return o;


                  template<typename A=manip_t
                  ,typename B=manip_t, typename C= manip_t
                  ,typename D=manip_t // to be continued
                  >
                  inline void LOG_ERROR(A&& a=no_manip, B&& b=no_manip,C&& c=no_manip
                  ,D&& d=no_manip /*to be continued*/)
                  LOG_ERROR_<A,B,C,D/*to be continued*/>(
                  std::forward<A>(a),std::forward<B>(b),std::forward<C>(c),
                  std::forward<D>(d)/*to be continued*/);



                  Depending on the compiler this code could produce ugly assembly. One solution is to write an overload for each possible number of argument, or have a good knowldge of compiler specific function attributes (always_inline,etc...)







                  share|improve this answer














                  share|improve this answer



                  share|improve this answer








                  edited Aug 16 at 9:15

























                  answered Aug 16 at 9:01









                  Oliv

                  6,4031747




                  6,4031747






















                       

                      draft saved


                      draft discarded


























                       


                      draft saved


                      draft discarded














                      StackExchange.ready(
                      function ()
                      StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51871383%2fvariadic-template-functions-no-matching-function-for-call-stdendl%23new-answer', 'question_page');

                      );

                      Post as a guest













































































                      這個網誌中的熱門文章

                      How to combine Bézier curves to a surface?

                      Mutual Information Always Non-negative

                      Why am i infinitely getting the same tweet with the Twitter Search API?