Variadic Template Functions: No matching function for call, std::endl
Clash 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
c++ c++11 variadic-templates
add a comment |Â
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
c++ c++11 variadic-templates
2
The issue is also discussed here. I don't think it's a duplicate though, as your question involves passingstd::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 asstd::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 theLOG_ERROR
function but I would like the user to be able to use the function withstd::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 asstd::endl
is used in a deducible context, which it isn't in your case.
â WhozCraig
Aug 16 at 7:36
add a comment |Â
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
c++ c++11 variadic-templates
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
c++ c++11 variadic-templates
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 passingstd::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 asstd::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 theLOG_ERROR
function but I would like the user to be able to use the function withstd::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 asstd::endl
is used in a deducible context, which it isn't in your case.
â WhozCraig
Aug 16 at 7:36
add a comment |Â
2
The issue is also discussed here. I don't think it's a duplicate though, as your question involves passingstd::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 asstd::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 theLOG_ERROR
function but I would like the user to be able to use the function withstd::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 asstd::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
add a comment |Â
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
add a comment |Â
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.
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
 |Â
show 1 more comment
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.
4
Possibly:auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl;
. it works also withstd::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 withstd::wcout
...
â Jarod42
Aug 16 at 7:40
 |Â
show 4 more comments
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...)
add a comment |Â
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
add a comment |Â
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
add a comment |Â
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
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
edited Aug 23 at 12:03
eneski
653520
653520
answered Aug 16 at 7:22
user2641018
805
805
add a comment |Â
add a comment |Â
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.
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
 |Â
show 1 more comment
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.
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
 |Â
show 1 more comment
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.
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.
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
 |Â
show 1 more comment
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
 |Â
show 1 more comment
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.
4
Possibly:auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl;
. it works also withstd::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 withstd::wcout
...
â Jarod42
Aug 16 at 7:40
 |Â
show 4 more comments
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.
4
Possibly:auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl;
. it works also withstd::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 withstd::wcout
...
â Jarod42
Aug 16 at 7:40
 |Â
show 4 more comments
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.
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.
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 withstd::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 withstd::wcout
...
â Jarod42
Aug 16 at 7:40
 |Â
show 4 more comments
4
Possibly:auto EndlWrap = (auto&&os) -> decltype(auto) return os << std::endl;
. it works also withstd::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 withstd::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
 |Â
show 4 more comments
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...)
add a comment |Â
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...)
add a comment |Â
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...)
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...)
edited Aug 16 at 9:15
answered Aug 16 at 9:01
Oliv
6,4031747
6,4031747
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f51871383%2fvariadic-template-functions-no-matching-function-for-call-stdendl%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
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 asstd::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 withstd::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