c++ passing a pointer to a template function as template - c++

I have this iter function that takes a pointer to value_type, a size_type, and a function pointer fun_type that is supposed to take a value_type& as parameter:
template <
class value_type,
class size_type,
class fun_type
> void iter(value_type *arr, size_type size, fun_type function)
{ while (size--) function(arr[size]); }
It works fine until we have a function that has a template, let's say for example we want to use this function:
template <
class T
> void print(const T &value) { std::cout << value << std::endl; }
Then we get this compilation error:
main.cpp:35:1: error: no matching function for call to 'iter'
iter( tab, 5, print );
^~~~
./iter.hpp:17:8: note: candidate template ignored: couldn't infer template argument 'fun_type'
> void iter(value_type *arr, size_type size, fun_type function)
^
main.cpp:36:1: error: no matching function for call to 'iter'
iter( tab2, 5, print );
^~~~
./iter.hpp:17:8: note: candidate template ignored: couldn't infer template argument 'fun_type'
> void iter(value_type *arr, size_type size, fun_type function)
How could I make fun_type work with every function no matter the template and the return type of the function?

Your iter function template requires a function for its third template parameter; but print (on its own) is not a function – it's a function template, and the compiler simply cannot deduce what template parameter to use in order to actually create a function … so you need to tell it! Just add the type of the tab array/pointer as that template parameter:
int main()
{
int tab[] = { 5,4,3,2,1 };
iter(tab, 5, print<int>);
return 0;
}

Related

Tagged structures casting rules

I was playing around with toy tuple implementations and eventually stuck with how get function works.
Consider this simple example
#include <iostream>
#include <utility>
template <size_t Tag, typename ValueType>
struct TagedValue { ValueType value; };
struct Test : TagedValue<0, int>, TagedValue<1, std::string>, TagedValue<2, double> {};
template <size_t Idx, typename T>
auto& get(Test& test) {
((TagedValue<Idx, T>&)(test)).value;
}
template <size_t Idx, typename T>
auto& get_impl(TagedValue<Idx, T>& tagged_value) {
return tagged_value.value;
}
template <size_t Idx>
auto& get_2(Test& test) {
return get_impl<Idx>(test);
}
int main()
{
Test test;
get_2<0>(test);
get<0>(test);
}
I get this error:
<source>: In function 'int main()':
<source>:29:16: error: no matching function for call to 'get<0>(Test&)'
29 | get<0>(test);
| ^
<source>:10:7: note: candidate: 'template<long unsigned int Idx, class T> auto& get(Test&)'
10 | auto& get(Test& test) {
| ^~~
<source>:10:7: note: template argument deduction/substitution failed:
<source>:29:16: note: couldn't deduce template parameter 'T'
29 | get<0>(test);
| ^
I do have couple of questions:
Basically why get_2 works and get doesn't compile. To me it looks like get_2 does exactly what I'm trying to do inside get
Does deducing T for get_2 take O(1) time, if yes how is it possible? Does compiler store some kind of map internally?
When you call a function template then all template arguments must either be specified explicitly or be deduced from the function arguments. When you call
get<0>(test);
Then Idx is 0, but there is no way for the compiler to know what T is supposed to be. The parameter is just Test, and T cannot be deduced from that.

How i colud use template function in arguments of template function?

I'm trying to realize some abstraction with functions in c++.
I want to do template function which takes two functions as arguments:
template <class inpOutp, class decis>
bool is_part_of_triangle(inpOutp ft_take_data,
decis ft_result){
return (ft_take_data(ft_result));
}
first one ft_take_data is template too and takes one function as argument:
template <class dec>
bool take_data(dec ft_result){
...
ft_result(cathetus_size, x_X, y_X);
...
}
second one ft_result should be the argument of ft_take_data:
int result(int cath_size, int x_X, int x_Y){
...
}
And i try to run it all in main like:
int main(void){
return (is_part_of_triangle(take_data, result));
}
But i have the error from compiler:
error: no matching function for call to 'is_part_of_triangle(<unresolved overloaded function type>, int (&)(int, int, int))'
return (is_part_of_triangle(take_data, result));
main.cpp:38:7: note: candidate: template<class inpOutp, class decis> bool is_part_of_triangle(inpOutp, decis)
bool is_part_of_triangle(inpOutp ft_take_data,
^~~~~~~~~~~~~~~~~~~
main.cpp:38:7: note: template argument deduction/substitution failed:
main.cpp:49:47: note: couldn't deduce template parameter 'inpOutp'
return (is_part_of_triangle(take_data, result));
How can i realize this scheme - run template function with two functions in arguments, one of which the template function too (which call second one):
-> func1(func2, func3);
-> in func1 { func2(func3); }
-> in func2 { func3(...); }
The take_data is a template not an real function of which the address/ function pointer can be passed.
In order to get a concrete function, the template must be instantiated.
That means you need to pass something like:
take_data<TYPE OF NON-TEMPLATE FUNCTION>
Or simply
take_data<decltype(FUNCTION)>
That means you can either
return is_part_of_triangle(&take_data<int (*)(int, int, int)>, &result);
Or
return is_part_of_triangle(&take_data<decltype(result)>, &result);
When take_data is a template function, you must specify its template when you pass this function as a parameter
You can do it like this:
typedef int(*RESULT_FUNC)(int, int, int);
return (is_part_of_triangle(&take_data<RESULT_FUNC>, &result));

Why can't this parameter pack accept function pointers?

I'm trying to create a parameter pack full of function pointers, but GCC (with c++17 standard) generates a deduction failed error. Why is that?
As written here:
For pointers to functions, the valid arguments are pointers to functions with linkage (or constant expressions that evaluate to null pointer values).
In my example, that's the case (isn't it?).
Is this rule invalidated for parameter packs? Did I miss something in the standard? If that's the case, how can I fix my code, without passing the function pointers as function arguments (ie without declaring T run2(T input, Funcs... funcs).
// In f.hpp
template<typename T>
T run2(T input)
{
return input;
}
template<typename T, T(*f)(T), class ... Funcs>
T run2(T input)
{
return run2<T, Funcs...>(f(input));
}
// In m.cpp
unsigned add2(unsigned v)
{
return v+2;
}
int main()
{
unsigned a=1;
a = run2<unsigned, add2>(a); // works
a = run2<unsigned, add2, add2>(a); // doesn't work
std::cout << a << std::endl;
return 0;
}
This the error I get with run2<unsigned, add2, add2> (GCC doesn't tell me why the last attempt actually failed):
m.cpp: In function ‘int main()’:
m.cpp:37:37: error: no matching function for call to ‘run2(unsigned int&)’
a = run2<unsigned, add2, add2>(a);
^
In file included from m.cpp:2:0:
./f.hpp:85:3: note: candidate: template<class T> T run2(T)
T run2(T input)
^
./f.hpp:85:3: note: template argument deduction/substitution failed:
m.cpp:37:37: error: wrong number of template arguments (3, should be 1)
a = run2<unsigned, add2, add2>(a);
^
In file included from m.cpp:2:0:
./f.hpp:109:3: note: candidate: template<class T, T (* f)(T), class ... Funcs> T run2(T)
T run2(T input)
^
./f.hpp:109:3: note: template argument deduction/substitution failed:
You declared a type parameter pack, class... Funcs. You can't pass function pointers as arguments for type parameters, because they are values, not types. Instead, you need to declare the run2 template so that it has a function pointer template parameter pack. The syntax to do so is as follows:
template<typename T, T(*f)(T), T(*...fs)(T)>
T run2(T input)
{
return run2<T, fs...>(f(input));
}
(The rule is that the ... is part of the declarator-id and goes right before the identifier, namely fs.)
The pack fs can accept one or more function pointers of type T (*)(T).

How to pass array to function template with reference

I am learning c++ template concepts. I do not understand the following.
#include <iostream>
#include <typeinfo>
using namespace std;
template <typename T>
T fun(T& x)
{
cout <<" X is "<<x;
cout <<"Type id is "<<typeid(x).name()<<endl;
}
int main ( int argc, char ** argv)
{
int a[100];
fun (a);
}
What i am trying?
1) T fun (T & x)
Here x is a reference, and hence will not decayed 'a' into pointer type,
but while compiling , i am getting the following error.
error: no matching function for call to ‘fun(int [100])’
When I try non-reference, it works fine. As I understand it the array is decayed into pointer type.
C-style arrays are very basic constructs which are not assignable, copyable or referenceable in the way built-ins or user defined types are. To achieve the equivalent of passing an array by reference, you need the following syntax:
// non-const version
template <typename T, size_t N>
void fun( T (&x)[N] ) { ... }
// const version
template <typename T, size_t N>
void fun( const T (&x)[N] ) { ... }
Note that here the size of the array is also a template parameter to allow the function to work will all array sizes, since T[M] and T[N] are not the same type for different M, N. Also note that the function returns void. There is no way of returning an array by value, since the array is not copyable, as already mentioned.
The problem is in the return type: you cannot return an array because arrays are non-copiable. And by the way, you are returning nothing!
Try instead:
template <typename T>
void fun(T& x) // <--- note the void
{
cout <<" X is "<<x;
cout <<"Type id is "<<typeid(x).name()<<endl;
}
And it will work as expected.
NOTE: the original full error message (with gcc 4.8) is actually:
test.cpp: In function ‘int main(int, char**)’:
test.cpp:17:10: error: no matching function for call to ‘fun(int [100])’
fun (a);
^
test.cpp:17:10: note: candidate is:
test.cpp:7:3: note: template<class T> T fun(T&)
T fun(T& x)
^
test.cpp:7:3: note: template argument deduction/substitution failed:
test.cpp: In substitution of ‘template<class T> T fun(T&) [with T = int [100]]’:
test.cpp:17:10: required from here
test.cpp:7:3: error: function returning an array
The most relevant line is the last one.

size_t and unsigned int does not match in a template function's parameter list

I want to use a stack to store indices of an array,so I use the following typedef,where istack is a template class for stack:
typedef istack<size_t> IndexStack;
and I declare a stack by
IndexStack stack;
But when I call the following function (where A.size() returns a size_t);
stack.push_back(A.size());
GCC gives the following error
sort.cpp: In function 'void quicksort2(Array&)':
sort.cpp:50:27: error: no matching function for call to 'istack<unsigned int>::push_back(size_t)'
iarray.h:103:8: note: candidate is: void istack<T>::push_back(T&) [with T = unsigned int]
How can I make it work?
#include <cstddef>
template <class T>
struct istack
{
void push_back(T& value);
std::size_t size() const;
};
int main()
{
typedef istack<size_t> IndexStack;
IndexStack a, stack;
stack.push_back(a.size());
}
This code produces an error
In function 'int main()':
13 no matching function for call to 'istack<unsigned int>::push_back(size_t)'
note 5 candidates are: void istack<T>::push_back(T&) [with T = unsigned int]
Note that it lists candidates. (I suspect you are not reading / posting the entire error message.)
The given candidate doesn't match the call, because the reference is non-const. A temporary (such as the result of a.size()) cannot be bound to a non-const reference.
push_back should be taking a const T& value