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

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

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.

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.

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

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

Related

non-type template parameters, partial specialization vs function argument in C++

Short question;
I don't get why this syntax exists:
template <int in>
void test(){
std::cout << in << std::endl;
}
int main(){
test<5>();
return 0;
}
When you can do the same without templates:
void test(test in){
std::cout << in << std::endl;
}
int main(){
test(5);
return 0;
}
How would you do this without templates?
template<std::size_t n> void f() {
char buf[n];
}
Besides, passing values as arguments requires extra arguments, extra run-time overhead, not necessarily needed when you know a value is actually a compile-time constant. With classes, it would require an extra member, and an extra construction argument for a class which might otherwise be empty and trivial.
What you have shown is not partial specialization.
Here an example of specialization (in this case full specialization):
#include <iostream>
template <int in, int in2>
void test_template(){
std::cout << in << std::endl;
}
template <>
void test_template<1>(){
std::cout << "one" << std::endl;
}
template <>
void test_template<2>(){
std::cout << "two" << std::endl;
}
int main()
{
test_template<1>();
test_template<2>();
test_template<3>();
test_template<4>();
}
And it is useful to handle certain template parameters in a special way. (Partial specialization, is if you have multiple template arguments and specialize all except one of them)
Regarding your example, the use-case you have shown does not illustrate where it can be useful, as it indeed does not make much a difference to use a regular function there.
But if you look at functions like std::make_shared or std::make_pair there is no way how you could solve that without using templates:
template< class T1, class T2 >
std::pair<T1,T2> make_pair(T1 t, T2 u) {
return std::pair<T1,T2>(t,u);
}
They are not "the same".
The two versions of test are very different. I rename them to avoid confusion and merely list some differences:
template <int in>
void test_template(){
std::cout << in << std::endl;
}
void test_fun(test in){
std::cout << in << std::endl;
}
test_template is a template. It is not a function. For example it is not possible to get a pointer to test_template:
auto f_ptr1 = &test_template; // doesn't make sense
auto f_ptr2 = &test_fun; // OK
The template parameter has to be known at compile time:
int x;
std::cin >> x;
test_template<x>(); // error: x must be known at compile time
test_fun(x); // OK
On the other hand, once you did instantiate the template you get a function with no parameters:
auto f = &test_template<5>;
f();
auto g = &test_template<6>;
g();
Similar you can only do with test_fun when you wrap it into another function (ie overhead).
... and more.
PS: There is no partial specialization in your code.

Template std::function as class member function C++

I would like to store a std::function in a class as a member.
I have troubles with below test code when calling a.callMethod() where the method has been set just before with a.setMethod(). The code works fine if I remove the template.
I have tried to debug with a function callMethodOutsideClass without success.
Is there a better way to manage that ?
#include <iostream>
#include <vector>
#include <functional>
template<typename T>
struct A
{
A(size_t size, T value) : vec_(size, value), method_(nullptr) {}
void setMethod(const std::function<int(A<T>&)> method) { method_ = method; }
int callMethod()
{
if(method_)
return method_(*this);
else
std::cerr << "method not initialized" << std::endl;
return -1;
}
std::vector<int> vec_;
std::function<int(A<T>& a)> method_;
};
template<typename T>
int callMethodOutsideClass(struct A<T>& a, const std::function<int(A<T>&)> method)
{
return method(a);
}
template<typename T>
int apple(struct A<T>& a)
{
a.vec_[0] += 1;
return 1;
}
template<typename T>
int orange(struct A<T>& a)
{
a.vec_[0] += 2;
return 2;
}
int main()
{
A<int> a(10,4), b(10,4);
std::cout << callMethodOutsideClass(a, &apple) << std::endl;
a.setMethod(&orange);
std::cout << a.callMethod() << std::endl;
std::cout << a.vec_[0] << std::endl;
}
I currently get the following errors :
Foo6.cpp: In function ‘int main()’:
Foo6.cpp:46:47: error: cannot resolve overloaded function ‘apple’ based on conversion to type ‘std::function<int(A<int>&)>’
std::cout << callMethodOutsideClass(a, &apple) << std::endl;
^
Foo6.cpp:48:21: error: no matching function for call to ‘A<int>::setMethod(<unresolved overloaded function type>)’
a.setMethod(&orange);
^
Foo6.cpp:48:21: note: candidate is:
Foo6.cpp:9:7: note: void A<T>::setMethod(std::function<int(A<T>&)>) [with T = int]
void setMethod(const std::function<int(A<T>&)> method) { method_ = method; }
^
Foo6.cpp:9:7: note: no known conversion for argument 1 from ‘<unresolved overloaded function type>’ to ‘std::function<int(A<int>&)>’
A pointer to function is not a std::function<T>. The std::function<T> signature can't be deduced based on the function address given as an argument. In addition, the compiler can't resolve a proper function template specialization to get its address when a conversion to std::function<T> is requested, since the constructor of std::function<T> is a function template as well.
You need to be more explicit:
std::cout << callMethodOutsideClass<int>(a, &apple<int>) << std::endl;
// ^^^^^ ^^^^^
a.setMethod(&orange<int>);
// ^^^^^
Is there any way to deduce templates parameters "easily" ?
You can modify the signature of callMethodOutsideClass in one of two ways:
Option #1:
Disable a type deduction on a std::function<int(A<T>&)> parameter:
template <typename T> struct identity { using type = T; };
template<typename T>
int callMethodOutsideClass(A<T>& a, const typename identity<std::function<int(A<T>&)>>::type method)
{
return method(a);
}
But you'll have to pay for the type-erasure applied by a std::function.
Option #2:
Let the compiler deduce the real type of a functor object given as an argument:
template <typename T, typename F>
int callMethodOutsideClass(A<T>& a, F&& method)
{
return std::forward<F>(method)(a);
}
In both cases you can just say:
callMethodOutsideClass(a, &apple<int>);
// ^^^^^
Note: You still have to pass the address of a concrete function template specialization by providing a list of template arguments &apple<int>. If you want to get away with a simple &address syntax, then the function taking it needs to declare an exact type of that argument:
template<typename T>
int callMethodOutsideClass(A<T>& a, int(*method)(A<T>&))
{
return method(a);
}
callMethodOutsideClass(a, &apple);
or you could help the compiler resolve the proper overload at a call site:
callMethodOutsideClass(a, static_cast<int(*)(decltype(a)&)>(&apple));
...or, you can use a lambda expression defined as follows:
template<typename T, typename F>
int callMethodOutsideClass(struct A<T>& a, F&& method)
{
return std::forward<F>(method)(a);
}
// in C++11:
callMethodOutsideClass(a, [](decltype(a)& x){return apple(x);});
// in C++14:
callMethodOutsideClass(a, [](auto&& x){return apple(std::forward<decltype(x)>(x));});
As far as the setMethod member function is concerned, the things are easier, since the compiler knows exactly that it expects const std::function<int(A<T>&)> method where T is known (not deduced). So basically, you just need to help the compiler to get the address of a function template specialzation you need at the call site:
a.setMethod(&orange<int>);
a.setMethod(static_cast<int(*)(decltype(a)&)>(&orange));

Why doesn't overloaded function bind to more specific overload?

Consider the following overloaded functions:
template <class T>
void foo(const T& v)
{
std::cout << "Generic version" << std::endl;
}
void foo(std::pair<const void*, std::size_t> p)
{
std::cout << "Pair version" << std::endl;
}
Below, I expect the second overload (the one that takes an std::pair) to be called:
int main()
{
const void* buf = 0;
std::size_t sz = 0;
foo(std::make_pair(buf, sz));
}
However, this code in fact calls the generic version. Why doesn't it bind to the overload that specifically takes an std::pair? Is this a compiler bug? I'm using a pretty old compiler, GCC 4.1.2
You need to declare your specialized function as a template
Your specialized argument type must follow the template parameter (i.e. be a const reference) as well.
Try
template <>
void foo(const std::pair<const void*, std::size_t>& p)
{
...
}

Templates for cout input

I want to create a function that takes in anything that the << operator for std::cout can handle. I have an example that breaks.
#include <iostream>
template <typename T>
void my_print(const T &t) {
std::cout << t;
}
int main() {
my_print("hello\n"); // works
my_print(4); // works
my_print(std::endl); // compiler error
return 0;
}
It also fails if I change to void my_print(T t). The compiler error is
error: no matching function for call to 'my_print(<unresolved overloaded function type>)'
note: candidate is
note: template<class T> void my_print(const T&)
Why can't the compiler resolve it when it sees that the argument t is being put into cout?
Is there any good way to fix this or do I have to manually provide the additional << cases, e.g. void my_print(ostream& (*pf)(ostream&));
EDIT: I know endl is a function. Is the answer then that function types are not accepted as templates? Like I can't have [T = ostream& (*)(ostream&)]?
std::endl is actually a function template. You can read the full documentation here or here. It is defined as:
template< class CharT, class Traits >
std::basic_ostream<charT,traits>& endl( std::basic_ostream<CharT, Traits>& os );
Edit: You can achieve what you want using this solution (which I vaguely adapted from here)
#include <iostream>
// handles the other types
template <typename T>
void my_print(const T &t) {
std::cout << t;
}
// alias a few things to make the prototypes readable
typedef std::basic_ostream<char, std::char_traits<char> > CoutType;
typedef CoutType& (*StandardEndLine)(CoutType&);
int main() {
my_print("hello\n"); // works
my_print(4); // works
my_print((StandardEndLine)std::endl); // <- NOTE: there is an explicit cast
return 0;
}

Which of two overloaded templates will be called?

I am still trying to figure out templates. I have read about the specialization rules and don't understand what is happening here.
I have defined the following in templates.h:
#include <iostream>
template <typename foo>
void f(foo p)
{
std::cout << "one" << std::endl;
}
template <typename bar>
void f(int p)
{
std::cout << "two" << std::endl;
}
Now if I include this and call it in my main like this
f(1);
f("x");
I get
one
one
Now the questions is, why is the first more specific than the second for ints? I feel like it should at least be ambiguous and not work at all.
First off, you don't have specializations, but two separate, unrelated overloads.
Secondly, the second overload is trivially non-viable, since you call the function without template arguments, and thus there is no way to deduce the template parameter bar. So only the first overload is viable, and gets used.
An actual specialization would look like this:
template <>
void f<int>(int p) { /* ... */ }
Better yet, stick with overloads (it's generally better to overload functions than to provide template specializations), but make the second one a non-template:
void f(int p) { /* ... */ }
The second overload one has no template dependency on function arguments, so you would have to call it like this:
f<std::string>(1);
f<double>(42);
f<SomeType>(1);
Whether it makes sense to have the second version is a different matter. You could imagine having a template parameter that does have some effect on the internal logic of the function:
template <typename SomeType>
int foo(int seed) {
// instantiate a SomeType and use it to calculate return value
};
int i = foo<Type1>(42);
int j = foo<Type2>(42);
On the other hand, your SomeType could be a function parameter:
template <typename SomeType>
int foo(int seed, const SomeType& s) {
// use s to calculate return value
};
Type1 t1;
Type2 t2;
int i = foo(42, t1);
int j = foo(42, t2);
In the second one bar cannot be deduced from function arguments, and must be given explicitly:
f<whatever>(1);
The one, which prints "two" is not recognized as explicit specialization. Try thisL
template <>
void f(int p)
{
std::cout << "two" << std::endl;
}