Passing template function as argument for normal function - c++

I'm wondering if it's possible to pass a template function (or other) as an argument to a second function (which is not a template).
Asking Google about this only seems to give info about the opposite ( Function passed as template argument )
The only relevant page I could find was http://www.beta.microsoft.com/VisualStudio/feedbackdetail/view/947754/compiler-error-on-passing-template-function-as-an-argument-to-a-function-with-ellipsis
(not very helpful)
I'm expecting something like:
template<class N>void print(A input){cout << input;}
void execute(int input, template<class N>void func(N)){func(input)}
and then later call
execute(1,print);
So, can this be done or would another template have to be defined for execute() ?

Function templates represent an infinite overload set, so unless you have a target type that is compatible with a specialization, deduction of the function type always fails. For example:
template<class T> void f(T);
template<class T> void h(T);
void g() {
h(f); // error: couldn't infer template argument 'T'
h(f<int>); // OK, type is void (*)(int)
h<void(int)>(f); // OK, compatible specialization
}
From above we can see that the validity of the program demands that we specify the template arguments for the function template, when in general it isn't always intuitive to specify them. You can instead make print a functor with a generic overloaded call operator as an extra level of indirection:
struct print {
template<typename T>
void operator()(T&& x) const {
std::cout << x;
}
};
Now you can have execute accept any Callable and invoke it with the input:
template<class T, class Op>
void execute(T&& input, Op&& op) {
std::forward<Op>(op)(std::forward<T>(input));
}
void g() { execute(1, print{}); }
Generic lambdas (C++14) make this a lot more concise:
execute(1, [] (auto&& x) { std::cout << x; });

Execute would need to be a template- there's no way for the compiler to create a single version of execute that would work for any input type. Now if you specified what N is for this specific function- for example if you made the second parameter print- then it should be legal.

Related

How do I add a template specialization when for a generic method on a generic class when the two types are equal?

I'm trying to add in a specialization where the generic type of method and class agree, but I haven't been able to figure out exactly how to specify the template instantiation (if it is even possible).
My best guess would be something like the following (though it obviously doesn't compile):
template<typename ClassT>
class Foo
{
public:
ClassT x;
template<typename MethodT>
void Bar(MethodT arg)
{
}
};
template<typename T>
template<>
void Foo<T>::Bar(T arg)
{
x = arg;
}
As is usually the case when considering function template specialization, an overload can handle it:
template<typename MethodT>
void Bar(MethodT arg)
{
}
void Bar(ClassT arg)
{
x = arg;
}
When you call Bar, one of the candidates will be a function template specialization and one won't. Think of the class template as stamping out real, concrete member functions where possible when it's instantiated. There's a rule pretty late in overload resolution to prefer the one that isn't a function template specialization if it's a tie up to that point.
What you end up with is the second overload being called when there's an "exact match" in types (which allows for a difference in top-level const). If exact matches are too narrow, you can restrict the first overload to widen the second:
// Allow the other overload to win in cases like Foo<int>{}.Bar(0.0).
// std::enable_if works as well before C++20.
template<typename MethodT>
void Bar(MethodT arg) requires (not std::convertible_to<MethodT, ClassT>)
{
}
As discussed in the comments, it's not possible to do this with template specialization. However, something similar can be accomplished by using std::enable_if_t and
template<typename ClassT>
class Foo
{
public:
ClassT x;
template<typename MethodT,
typename = std::enable_if_t<!std::is_same<ClassT, MethodT>::value>>
void Bar(MethodT arg)
{
}
void Bar(ClassT arg)
{
x = arg;
}
};
std::enable_if_t will only return a valid type when the input type arg is true. Therefore, the template substitution will fail when MethodT and ClassT are the same type, but the non-template overload will not fail. The template substitution failure is ok under SFINAE.

C++ overload resolution with template

I want to have a function that takes a std::string and another that takes anything that is not a std::string.
So I have:
#include <iostream>
#include <string>
void foo(const std::string& str) {
std::cout << "string version called" << std::endl;
}
template<class T>
void foo(T&& str) {
std::cout << "template version called" << std::endl;
}
int main() {
foo(std::string{"hello"});
return 0;
}
The problem is that the templated version is called instead of the std::string version.
So how can I have a foo function that either takes anything or specifically a std::string?
The templated foo is using forwarding reference, when being passed temporary std::string like std::string{"hello"}, after the deduction the function parameter str would be std::string&&, it's a better match than the non-template foo which taking const std::string&.
You can impose restrictions on the template parameter to make it usable only when being passed non-std::strings. E.g.
template<class T>
std::enable_if_t<!std::is_same_v<std::decay_t<T>, std::string>>
foo(T&& str) {
std::cout << "template version called" << std::endl;
}
LIVE
Your problem is you are taking by forwarding reference. An rvalue binds to std::string&& better than std::string const&, so yourtemplate ks preferred.
Change it to
template<class T>
void foo(T const& str) {
std::cout << "template version called" << std::endl;
}
use typeid()
template <class T>
void foo(T &&str)
{
if (typeid(str) == typeid(string))
{
std::cout << "string version called" << std::endl;
}else{
std::cout << "template version called" << std::endl;
}
}
int main() {
foo(std::string{"hello"});
foo("hello");
return 0;
}
The problem with your code is that you are creating a temporary variable std::string{"Hello"} which is an exact match for T&& (better than std::string const&) and therefore the templated version is chosen. You could either
Specialise the template for std::string
template<typename T>
void foo(T t) {
// Your implementation for other data types
}
// Template specialisation for strings
template <>
void foo<std::string>(std::string str) {
// Your implementation for strings goes here
}
Overload the function and de-activate the template for std::string, std::string const&, std::string&&, ... For the latter you can use the std::decay<T> type trait struct to disable all of these versions at once in combination with std::is_same.
// Function overload for strings
void foo(std::string const& str) {
// Your implementation for strings goes here
}
// Template disabled for strings
template<class T>
typename std::enable_if<!std::is_same<std::decay<T>::type, std::string>::value>::type
foo(T&& t) {
// Your implementation for the other data types
}
You could compare the typeid or even better in C++17 there is a constexpr if available which could be combined with std::is_same<T>
template<class T>
void foo(T&& t) {
if constexpr (std::is_same_v<T, std::decay_t<std::string>>) {
// Your implementation for strings
} else {
// Your implementation for the other data types
}
}
Furthermore if you wanted to make something like
foo("Hello");
work as well (so instead of foo(std::string{"Hello"})) you could take it a step further also excluding any sort of char*
// Gets used for std::string as well as char*
void foo(std::string const& str) {
std::cout << "string version called" << std::endl;
}
// Disable template for any std::string and char*
template<class T>
typename std::enable_if<!std::is_same<typename std::decay<T>::type, std::string>::value &&
!std::is_same<typename std::decay<T>::type, char const *>::value &&
!std::is_same<typename std::decay<T>::type, char *>::value>::type
foo(T&& t) {
std::cout << "template version called" << std::endl;
}
In this case also foo("Hello") will call the overloaded std::string version. Without this any call without std::string{} will go to the templated version! Try it hereC++11 C++17.
Use an explicit specialization rather than an overloaded function.
template<>
void foo<std::string>(const std::string& str) {
...
I think that's right; explicit specializations of free functions was not original to C++98 but added later at some point.
(it's still a pain to get right, as your specialization has to match the actual type that was deduced for T, which may include const and & if those were not present in the argument list; I've used it effectively for plain pass-by-value types like when the special type is int)
In C++20, you could use a requires clause to make the template not apply for std::string. If requires is not available, you can do the same thing using enable_if.
You might also just write one function, but use constexpr if in the body to provide the special case. This prevents the overloading mechanism from getting involved at all, and lets you code the exact rules for determining the special case.
Update: something old and something new
In the original template specification, function templates could not be explicitly specialized and the idea was that you overload functions instead. You see why this doesn't work as intended: the template is always an exact match, even when the specific function would be called (using trivial conversions, adding const, passing by reference) if overloading just non-template functions.
The work-around was to make a dummy class template, holding a static member function. So, if you originally had a function template f and you needed to explicitly specialize it, move the function body into:
template <typename T>
struct C {
void f (const T&) { /* body goes here */ }
};
Now you can write an explicit specialization of C, and thus C::f:
template<>
struct C<std::string> {
static void f (const std::string&) { /* special code goes here */ }
};
and then, to retain compatibility with the existing code, write a new body for the (non-member) f that just calls C<T>::f.
Now, doing that today you would make it even better and use perfect forwarding.
template <typename T>
void f (const T&& param)
{
C<T>::f(std::forward<T>(param));
}
Now, look at how this differs from just being able to explicitly specialize a function. The template argument deduction is done on the wrapper call, and then the determined value of T is used for the class template instantiation, and then the final member function call does not do any deduction but rather will apply conversions as for normal function calls. It doesn't have the "always a perfect match" behavior. The exact form of the argument can vary; e.g. whether you are passing a value or a const reference.
In fact, thanks to perfect forwarding, it preserves the value category of the wrapper's call, and you can actually overload f within one of the explicit specializations! That is, you could have a separate form for rvalues, constants or non-const, etc.
Here, the wrapper function was declared with const which loses the ability to distinguish non-const parameters, but this makes it easy to have template argument deduction not include the const. You could add your own normalization step to transform the actual argument's type into the plain T you wanted, instead. In fact, you can add any metaprogramming logic you want, such as recognising base and derived classes, which is another issue that shows up with overloading and templates.

Promotion of C++ overloaded function pointer to a function object

A C++11 template function which takes a function object argument, such as:
template <typename F, typename T>
auto foo(F f, T x) -> decltype(f(x)) {
return f(x);
}
could take a function such as:
int succ(int i) { return i+1; }
and apply foo to succ and obtain a result of 10:
foo(succ,9);
Overloaded functions don't work, sin, for example, fails:
foo(std::sin,0.5);
in GCC (4.7) with "couldn't deduce template parameter F".
(Providing sin<double> relates only to complex types btw.) Yes, I can struct it right up:
template <typename T>
struct Sin {
T operator()(T x) { return std::sin(x); }
};
with a little:
foo(Sin<double>(),0.5);
My question is, is there an alternative which avoids the need for such a new definition; usable solely at the call site of foo?
For function pointers, you can simply have the user type the signature:
template<class F, class T>
void foo(F f, T x){
f(x);
}
void bar(int){}
void bar(double){}
int main(){
foo<void(int)>(bar, 5);
}
Live example on Ideone.
foo will be void foo(void f(int), int x) after substitution, which is the same as foo(void (*f)(int), int x). This provides a so-called "calling context" which allows the compiler to select the correct overload. Obviously, this only works well if the first template parameter is the function. To work around this limitation, and make it look nicer (imho, atleast), you can provide a simple helper function:
template<class F>
auto get_overload(F f) -> decltype(f) { return f; }
Actually, you can only overload on parameter types, but this you can't cull out the need to have the user type the return type, since this disables the calling context again, as a type would need to be deduced.
Since you most likely (or surely) only want this for function pointers, you can change it to this:
template<class F>
F* get_overload(F* f){ return f; }
It's still completely the same. The only reason why the first version can't just have F as the return type is that F is void(int) if you call it with get_overload<void(int)>(bar), and the standard doesn't allow you to return functions (yes, that's a function type). The function to function pointer transformation (void(int) -> void(*)(int)) part only happens for parameters.
Since for whatever reason #VJovic deleted his answer, I'll just edit this in:
You can actually use a simple lambda instead of the get_overload function. It will be about the same length character wise and much more convenient and clearer. It will also be more efficient, since no (function) pointers are involved and the compiler is perfectly able to inline the call.
foo([](int i){ return bar(i); }, 5);

Is there a generic way to adapt a function template to be a polymorphic function object?

I have some function templates, for example
template <typename T>
void foo(T);
template <typename T>
void bar(T);
// others
and I need to pass each one to an algorithm that will call it with various types, e.g.
template <typename F>
void some_algorithm(F f)
{
// call f with argument of type int
// call f with argument of type SomeClass
// etc.
}
I can't pass in my function template uninstantiated, but I can't instantiate it with any specific type either because some_algorithm will need to call it with arguments of several different types.
I could adapt my function templates to be polymorphic function objects, e.g.
struct foo_polymorphic
{
template <typename T>
void operator()(T t)
{
foo(t);
}
};
and then pass it as some_algorithm(foo_polymorphic()). But this requires writing a separate adapter for each of my function templates.
Is there a generic way of adapting a function template to be a polymorphic function object, i.e. some mechanism that I can re-use for each of the function templates I need to adapt, without having to declare something separately for each one?
The short version of the problem is given an overloaded name f, how to concisely write an object ff such that ff(a0, a1, a2, ...) ultimately calls f(a0, a1, a2, ...).
A polymorphic functor, how you point out yourself, is the usual solution. But it must be defined out of line (since it has a template member), so I'll consder that not concise enough for the purposes of my answer.
Currently lambda expressions yield a monomorphic functor, so they're close but not quite there.
// set of functions overloaded on int and double
void f(int);
void f(double);
auto ff = [](int i) { return f(i); };
As GMan pointed out in the comments polymorphic lambdas would (should?) be the solution to concisely write polymorphic functors inline.
In the meantime, it is possible to write a make_overload helper that combines multiple functors into one, such that
auto ff = make_overload(
[](int arg0) { return f(arg0); }
, [](double arg0) { return f(arg0); } );
would 'capture' the whole overload set. Perhaps a Boost.Preprocessor macro could help here, so that auto ff = POLYMORPHIC_LAMBDA( 1, (int)(double), { return f(arg0); } ); be used inline. I suspect there are arity restrictions however (hence the first macro argument), unlike the usual out-of-line hand-written polymorphic functor solution; so this wouldn't help with e.g. variadic function templates.
Why couldn't you use template template parameters? You said you can't pass your template uninstantiated, but I'm not sure if you've heard of this before, tell me if you have and it won't work.
I don't know what your code structure looks like, but can you do something like
I know this works, don't know if it's what yo uwant though:
template<typename T>
T some_algorithm(T data) { return T(); } // just returning nothing for example
template<typename T, T(*Something)(T)>
class FuncClass {
public:
T run(T data) { return Something(data); }
};
template<typename T, typename Functor>
void apply_algorithm(T data) {
Functor F;
F.run(data);
}
int main() {
int mydata = 4;
apply_algorithm<int, FuncClass<int, some_algorithm<int> > >(mydata);
cin.get();
}

How to call a templated function if it exists, and something else otherwise?

I want to do something like
template <typename T>
void foo(const T& t) {
IF bar(t) would compile
bar(t);
ELSE
baz(t);
}
I thought that something using enable_if would do the job here, splitting up foo into two pieces, but I can't seem to work out the details. What's the simplest way of achieving this?
There are two lookups that are done for the name bar. One is the unqualified lookup at the definition context of foo. The other is argument dependent lookup at each instantiation context (but the result of the lookup at each instantiation context is not allowed to change behavior between two different instantiation contexts).
To get the desired behavior, you could go and define a fallback function in a fallback namespace that returns some unique type
namespace fallback {
// sizeof > 1
struct flag { char c[2]; };
flag bar(...);
}
The bar function will be called if nothing else matches because the ellipsis has worst conversion cost. Now, include that candidates into your function by a using directive of fallback, so that fallback::bar is included as candidate into the call to bar.
Now, to see whether a call to bar resolves to your function, you will call it, and check whether the return type is flag. The return type of an otherwise chosen function could be void, so you have to do some comma operator tricks to get around that.
namespace fallback {
int operator,(flag, flag);
// map everything else to void
template<typename T>
void operator,(flag, T const&);
// sizeof 1
char operator,(int, flag);
}
If our function was selected then the comma operator invocation will return a reference to int. If not or if the selected function returned void, then the invocation returns void in turn. Then the next invocation with flag as second argument will return a type that has sizeof 1 if our fallback was selected, and a sizeof greater 1 (the built-in comma operator will be used because void is in the mix) if something else was selected.
We compare the sizeof and delegate to a struct.
template<bool>
struct foo_impl;
/* bar available */
template<>
struct foo_impl<true> {
template<typename T>
static void foo(T const &t) {
bar(t);
}
};
/* bar not available */
template<>
struct foo_impl<false> {
template<typename T>
static void foo(T const&) {
std::cout << "not available, calling baz...";
}
};
template <typename T>
void foo(const T& t) {
using namespace fallback;
foo_impl<sizeof (fallback::flag(), bar(t), fallback::flag()) != 1>
::foo(t);
}
This solution is ambiguous if the existing function has an ellipsis too. But that seems to be rather unlikely. Test using the fallback:
struct C { };
int main() {
// => "not available, calling baz..."
foo(C());
}
And if a candidate is found using argument dependent lookup
struct C { };
void bar(C) {
std::cout << "called!";
}
int main() {
// => "called!"
foo(C());
}
To test unqualified lookup at definition context, let's define the following function above foo_impl and foo (put the foo_impl template above foo, so they have both the same definition context)
void bar(double d) {
std::cout << "bar(double) called!";
}
// ... foo template ...
int main() {
// => "bar(double) called!"
foo(12);
}
litb has given you a very good answer. However, I wonder whether, given more context, we couldn't come up with something that's less generic, but also less, um, elaborate?
For example, what types can be T? Anything? A few types? A very restricted set which you have control over? Some classes you design in conjunction with the function foo? Given the latter, you could simple put something like
typedef boolean<true> has_bar_func;
into the types and then switch to different foo overloads based on that:
template <typename T>
void foo_impl(const T& t, boolean<true> /*has_bar_func*/);
template <typename T>
void foo_impl(const T& t, boolean<false> /*has_bar_func*/);
template <typename T>
void foo(const T& t) {
foo_impl( t, typename T::has_bar_func() );
}
Also, can the bar/baz function have just about any signature, is there a somewhat restricted set, or is there just one valid signature? If the latter, litb's (excellent) fallback idea, in conjunction with a meta-function employing sizeof might be a bit simpler. But this I haven't explored, so it's just a thought.
I think litb's solution works, but is overly complex. The reason is that he's introducing a function fallback::bar(...) which acts as a "function of last resort", and then goes to great lengths NOT to call it. Why? It seems we have a perfect behavior for it:
namespace fallback {
template<typename T>
inline void bar(T const& t, ...)
{
baz(t);
}
}
template<typename T>
void foo(T const& t)
{
using namespace fallback;
bar(t);
}
But as I indicated in a comment to litb's original post, there are many reasons why bar(t) could fail to compile, and I'm not certain this solution handles the same cases. It certainly will fail on a private bar::bar(T t)
If you're willing to limit yourself to Visual C++, you can use the __if_exists and __if_not_exists statements.
Handy in a pinch, but platform specific.
EDIT: I spoke too soon! litb's answer shows how this can actually be done (at the possible cost of your sanity... :-P)
Unfortunately I think the general case of checking "would this compile" is out of reach of function template argument deduction + SFINAE, which is the usual trick for this stuff. I think the best you can do is to create a "backup" function template:
template <typename T>
void bar(T t) { // "Backup" bar() template
baz(t);
}
And then change foo() to simply:
template <typename T>
void foo(const T& t) {
bar(t);
}
This will work for most cases. Because the bar() template's parameter type is T, it will be deemed "less specialised" when compared with any other function or function template named bar() and will therefore cede priority to that pre-existing function or function template during overload resolution. Except that:
If the pre-existing bar() is itself a function template taking a template parameter of type T, an ambiguity will arise because neither template is more specialised than the other, and the compiler will complain.
Implicit conversions also won't work, and will lead to hard-to-diagnose problems: Suppose there is a pre-existing bar(long) but foo(123) is called. In this case, the compiler will quietly choose to instantiate the "backup" bar() template with T = int instead of performing the int->long promotion, even though the latter would have compiled and worked fine!
In short: there's no easy, complete solution, and I'm pretty sure there's not even a tricky-as-hell, complete solution. :(
//default
//////////////////////////////////////////
template <class T>
void foo(const T& t){
baz(t);
}
//specializations
//////////////////////////////////////////
template <>
void foo(const specialization_1& t){
bar(t);
}
....
template <>
void foo(const specialization_n& t){
bar(t);
}
Are you not able to use full specialisation here (or overloading) on foo. By say having the function template call bar but for certain types fully specialise it to call baz?