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));
Related
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;
}
I am trying to call a variadic function template using std::invoke() and std::apply().
And I apologize ahead of time, because I'm basically dropping a snippet of code here and asking someone to help me understand the error messages to solve the problem.
So, in the example code below,
std::invoke() on the non-variadic template functions works fine.
std::invoke() on the variadic template function does not compile!
#include <functional>
#include <tuple>
struct Thing
{
// Some simple functions to test things out
int func0() { return 0; }
int func1(int) { return 1; }
int func2(int, int) { return 2; }
// A variadic template function that causes problems below
template<typename ...Args>
int funcn(Args&&...) { return 99; }
};
int main()
{
Thing thing;
// These work fine
std::invoke(&Thing::func0, thing);
std::invoke(&Thing::func1, thing, 1);
std::invoke(&Thing::func2, thing, 1, 2);
// This one doesn't work
std::invoke(
&Thing::funcn,
thing,
1, 2, 3, 4
);
}
The errors I'm getting are here: (Output of x86-64 clang 12.0.1 (Compiler #1))
Wrap lines
<source>:26:5: error: no matching function for call to 'invoke'
std::invoke(
^~~~~~~~~~~
functional:94:5: note: candidate template ignored: couldn't infer template argument '_Callable'
invoke(_Callable&& __fn, _Args&&... __args)
^
The std::invoke expect a callable function. The funcn is a function template, and you need to instantiate to get a real function out of it and there-by you can take the address of it.
That means (explicitly) provide the template parameter to the function, how you want to instantiate it, so that std::invoke can see the function which it can invoke.
std::invoke(
&Thing::funcn<int, int, int, int>, // works now
thing,
1, 2, 3, 4
);
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).
I'm trying to make a function that takes a variable number of parameters of any type, but even the simple example I made is getting an error
#include <iostream>
#include <functional>
template<class... Ts>
void callFunction(const std::function<void(Ts...)>& function, Ts... parameters)
{
function(parameters...);
}
void myFunc(const std::string& output)
{
std::cout << output << std::endl;
}
int main()
{
callFunction<const std::string&>(&myFunc, "Hello world");
return 0;
}
When I run the above code in Ideone, I get this error:
prog.cpp: In function ‘int main()’:
prog.cpp:17:57: error: no matching function for call to ‘callFunction(void (*)(const string&), const char [12])’
callFunction<const std::string&>(&myFunc, "Hello world");
^
prog.cpp:5:6: note: candidate: template<class ... Ts> void callFunction(const std::function<void(Ts ...)>&, Ts ...)
void callFunction(const std::function<void(Ts...)>& function, Ts... parameters)
^~~~~~~~~~~~
prog.cpp:5:6: note: template argument deduction/substitution failed:
prog.cpp:17:57: note: mismatched types ‘const std::function<void(Ts ...)>’ and ‘void (*)(const string&) {aka void (*)(const std::__cxx11::basic_string<char>&)}’
callFunction<const std::string&>(&myFunc, "Hello world");
A simple suggestion: receive the callable as a deduced typename, not as a std::function
I mean (adding also perfect forwarding)
template <typename F, typename ... Ts>
void callFunction(F const & func, Ts && ... pars)
{ func(std::forward<Ts>(pars)...); }
and, obviously, call it without explicating nothing
callFunction(&myFunc, "Hello world");
This as the additional vantage that avoid the conversion of the callable to a std::function.
Anyway, I see two problems in your code:
1) if you receive the functional as a std::function receiving a list ot arguments types (a variadic list in this case, but isn't important for this problem) as a list of argument of the same types, you have to be sure that the types in the two list match exactly.
This isn't your case because the function receive a std::string const & and you pass as argument a the string literal "Hello world" that is a char const [12] that is a different type.
When the types are to be deduced, this cause a compilation error because the compiler can't choose between the two types.
You could solve receiving two list of types
template <typename ... Ts1, typename Ts2>
void callFunction (std::function<void(Ts1...)> const & function,
Ts2 && ... parameters)
{ function(std::forward<Ts2>(parameters)...); }
but now we have the second problem
2) You pass a pointer function (&myFunc) where callFunction() wait for a std::function.
We have a chicken-egg problem because &myFunc can be converted to a std::function but isn't a std::function.
So the compiler can't deduce the Ts... list of types from &myFunc because isn't a std::function and can't convert &myFunc to a std::function because doesn't know the Ts... type list.
I see that you have explicated the first type in the Ts... list, but isn't enough because the Ts... list is a variadic one so the compiler doesn't know that there is only a type in the Ts... list.
A simple solution to this problem is pass the function as a simple deduced F type.
Otherwise, if you have written callFunction() with two templates types lists, you can pass a std::function to the function
std::function<void(std::string const &)> f{&myFunc};
callFunction(f, "Hello world");
but I don't think is a satisfactory solution.
I want to create a function that returns different types of data-types for different input string. I am using templates for it but seems like I am making some mistake.
template<typename S>
S select(string type){
int integer;
float floaty;
char character;
string strings;
if(type=="int")
return integer;
if(type=="char")
return character;
if(type=="float")
return floaty;
if(type=="string")
return strings;
}
it gives this error when I run it will string argument int .
sam.cpp:771:13: error: no matching function for call to ‘select(std::string&)’
select(type);
^
sam.cpp:771:13: note: candidates are:
In file included from /usr/include/x86_64-linux-gnu/sys/types.h:219:0,
from /usr/include/stdlib.h:314,
from Markup.h:12,
from sam.cpp:3:
/usr/include/x86_64-linux-gnu/sys/select.h:106:12: note: int select(int, fd_set*, fd_set*, fd_set*, timeval*)
extern int select (int __nfds, fd_set *__restrict __readfds,
^
/usr/include/x86_64-linux-gnu/sys/select.h:106:12: note: candidate expects 5 arguments, 1 provided
sam.cpp:17:3: note: template<class S> S select(std::string)
S select(string type){
^
sam.cpp:17:3: note: template argument deduction/substitution failed:
sam.cpp:771:13: note: couldn't deduce template parameter ‘S’
select(type);
If it is wrong way and there is a better way of doing things then do share, Thanks.
In C++ template type deduction is based on parameter and not on return type so, in your particular case, when you are calling the function select, you have to explicitly specify the template argument.
then how will I achieve what I want to do with this function?
Use template specialization.
template<typename S>
S select(){
static_assert("Not Implemented");
}
template<> int select<int>() {
int integer;
//To Do
return integer;
}
template<> float select<float >() {
float floaty;
//To Do
return floaty;
}
//Remaining Specialization
and call the respective specialization using explicit template parameter
int main()
{
int _integer = select<int>();
float _float = select<float>();
..........
}
There's no way this can work. Templates require their parameters to be known at compile time, but the value of type is only known at run time.
If S is int then return strings won't compile, but if S is string then return integer won't compile.
And as others have pointed out S cannot be deduced, so you have to specify it explicitly in the call. But it still can't work for the reason above.
(Quite apart from all that, you haven't initialised any of the values.)