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;
}
Related
Assume that I want to implement operator<< for all types. I would do:
template <typename T>
std::ostream& operator<<(std::ostream& out, T&& t) {
return out << "DEFAULT";
}
But this won't work because of ambiguity (in cases where the already specified operator<< is a free function). So I tried to restrict this with a concept:
template <typename T>
concept printable = requires(const T& t, std::ostream& out) {
out << t;
};
This correctly reports that ints, std::strings and whatnot are printable, but std::vectors or some_user_defined_structs (without overloaded <<) are not.
What I wanted was to use this concept with my (overly generic) operator<<:
#include <iostream>
#include <vector>
template <typename T>
concept printable = requires(const T& t, std::ostream& out) {
out << t;
};
template <typename T>
requires (!printable<T>)
std::ostream& operator<<(std::ostream& out, T&& t) {
return out << "DEFAULT";
}
int main() {
std::cout << std::vector<int>();
}
But this lead to:
In instantiation of 'std::ostream& operator<<(std::ostream&, T&&) [with T = const char (&)[8]]':
recursively required from 'std::ostream& operator<<(std::ostream&, T&&) [with T = const char (&)[8]]'
required from 'std::ostream& operator<<(std::ostream&, T&&) [with T = const char (&)[8]]'
required from here
fatal error: template instantiation depth exceeds maximum of 900 (use '-ftemplate-depth=' to increase the maximum)
6 | out << t;
| ~~~~^~~~
compilation terminated.
It seems that there is an instantiation loop. In order to check whether we should use my <<, printable is being checked and by doing so, << is attempted to be generated, which leads to a loop.
Is there any mechanism that would prevent such loop? Can we constrain types in such a way that the template will be generated only if it needs to? As for the use-cases, assume that, for some reason, I never want the compilation to fail when someone tries to << something to std::cout.
You can't provide an operation if and only if the operation isn't provided. That's inherently self-recursive.
What you can do instead is add another layer of indirection. Like so:
template <typename T>
void print(std::ostream& os, T&& t) {
if constexpr (printable<T>) {
os << t;
} else {
os << "DEFAULT";
}
}
I was messing around with this and was able to come up with something similar to what the question describes, the only difference being that you have to opt in to using it via a using namespace directive. (godbolt demo)
#include <iostream>
#include <vector>
#include <utility>
template <typename T>
// T can be a reference type
concept printable = requires(std::ostream& out, T t) {
out << std::forward<T>(t);
};
template <typename T>
requires (!printable<T>)
std::ostream& default_print(std::ostream& out, T&& t) {
return out << "DEFAULT";
}
namespace default_ostream
{
template<typename T>
std::ostream& operator<<(std::ostream& out, T&& t)
requires requires { default_print(out, std::forward<T>(t)); }
{
return default_print(out, std::forward<T>(t));
}
} // namespace default_ostream
int main()
{
using namespace default_ostream;
std::cout << std::vector{ 0, 1, 2 } << '\n';
std::cout << "Hello!\n";
std::cout << 2.234 << '\n';
}
This program will output the following with all of GCC, Clang and MSVC:
DEFAULT
Hello!
2.234
Putting the default operator<< in a seperate namespace and deferring the !printable<T> requirement to print_generic seems to work. With this you will have to do using namespace default_ostream; if you want this behaviour, which cannot appear at global scope, but is fine at function (or some namespace) scope.
This works because printable doesn't see the generic operator<< when it's used as a requirement to default_print, that way it can't get selected for out << std::forward<T>(t) in the requirement and avoids recursive instantiation.
When you want to use the generic operator<<, you have to bring it into the local scope with using namespace default_ostream;, so it participates in overload resolution and because of its requirement it will only get selected if there's no other operator<< available.
I'm observing some seemingly strange behavior when trying to instantiate a template function.
In brief, I'm implementing a template function library. For the purposes of this library, I am assuming that for each type T used to instantiate one of these templates, the user of this library will have implemented a function with a specific signature, say:
void foo(const T& t)
I would like to define my library template functions within an enclosing namespace, say A. Similarly, I would like these functions to be usable within another (user-defined) namespace, say B. The overall usage pattern I have in mind is the following:
#include <string>
#include <iostream>
// My library function
namespace A {
template <typename T>
void my_library_function(const T& t) { foo(t); }
}
// Intended usage
namespace B {
// User writes a function foo(T) for the specific type T they want
// to use in conjunction with my_library_function()
void foo(const std::string& s) { std::cout << s << std::endl; }
// User can then use my_library_function() in their own code
void super_cool_user_function(const std::string& s) { A::my_library_function<std::string>(s); }
}
int main()
{
std::string s = "Hello world!";
B::super_cool_user_function(s);
}
I would expect this to work, since in this code my_library_function() is only used within the same namespace B where foo(std::string& s) is defined. However, when trying to compile this, I get the following error:
> In instantiation of ‘void A::my_library_function(const T&) [with T =std::__cxx11::basic_string<char>]’:
>
> example.cpp:8:43: error: ‘foo’ was not declared in this scope
>
> void my_library_function(const T& t) { foo(t); }
>
>example.cpp:8:43: note: suggested alternative:
>
>example.cpp:17:6: note: ‘B::foo’
>
>void foo(const std::string& s) { std::cout << s << std::endl; }
So, I have two (hopefully straightforward?) questions:
Why is this error occurring?
Is there a clean way of modifying my approach (the implementation of the template) to enable the intended usage shown above?
Thanks!
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...)
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));
This question already has answers here:
Priority when choosing overloaded template functions in C++
(6 answers)
Closed 3 years ago.
How do I force compiler to pick up a template function overload for a base class?
Here is an example that illustrates the question
#include <iostream>
class A
{};
class B : public A
{};
template <class T>
void f (const T& t)
{
std::cout << "Generic f" << std::endl;
}
void f (const A& a)
{
std::cout << "Overload for A" << std::endl;
}
template <class T>
void call_f (const T& t)
{
f (t);
}
int main()
{
call_f (10);
call_f (A());
call_f (B());
return 0;
}
It produces the output
Generic f
Overload for A
Generic f
Why doesn't the compiler pick up f (const A&) in the 3rd case? UPD: OK, this one is clear void f<B> (const B&) is better than void f (const A&), but I'm still looking for answer to the 2nd question.
And is it possible to force it to do so without casting B to A?
Using call_f(B()) results in a call to `f() which is best matched by the template version. For the non-template version a conversion is required. As a result, the template is chosen. If the template and the non-template would be equally good options, the non-template would be preferred.
If you want to the non-template to be called, you'll need to make the template a non-option. for example, the template could be implemented like
#include <type_traits>
template <class T>
typename std::enable_if<!std::is_base_of<A, T>::value>::type f(T const&)
{
std::cout << "Generic f\n";
}
If C++11 can't be used you could either implement a version of std::is_base_of<...>, use a version from Boost or use a simple dispatch:
struct true_type {};
struct false_type {};
true_type A_is_base_of(A const*) { return true_type(); }
false_type A_is_base_of(void const*) { return false_type(); }
template <class T>
void f (T const&, false_type)
{
std::cout << "Generic f\n";
}
void f (A const&, true_type)
{
std::cout << "Overload for A\n";
}
template <class T>
void call_f (const T& t)
{
f (t, A_is_base_of(&t));
}
I think this actually is possible. The trick is to make use of the fact that overload resolution prefers pretty much anything to a C-style variadic function argument. That way we can create helper functions that support tagged dispatch by constructing the appropriate tag for us. Overload resolution of the helper function forces the compiler to remove the generic template function from its list of candidate functions, leaving only the specialized function.
This is a lot more clear with code, so let's take a look.
#include <iostream>
struct foo {};
struct bar : public foo {};
struct generic_tag {};
struct foo_tag {};
generic_tag make_tag(...) {
return generic_tag();
}
foo_tag make_tag(foo const *) {
return foo_tag();
}
template<typename T>
void f(T const &t, generic_tag) {
std::cout << "Generic" << std::endl;
}
void f(foo const &f, foo_tag) {
std::cout << "Specialized" << std::endl;
}
template<typename T>
void call_f(T const &t) {
// This is the secret sauce. The call to make_tag(t) will always
// select the most specialized overload of make_tag() available.
// The generic make_tag() will only be called if the compiler can't
// find some other valid version of make_tag().
f(t, make_tag(&t));
}
int main() {
call_f( 10); // Prints "Generic"
call_f(foo()); // Prints "Specialized"
call_f(bar()); // Prints "Specialized"
}
I verified this solution works on Ununtu 14.04 using GCC 4.8.2.
Assuming that you know that what you are calling call_f on will always be a derived type of A, you can simply explicitly ask for that version of the template, like so:
call_f<A> (B());
If you actually call it with a type that is not convertible to A, like a third class
class C
{};
You should get a compiler error addressing this problem (along the lines of "error C2664: 'call_f' : cannot convert parameter 1 from 'C' to 'const A &")