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.)
Related
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));
Here is an example of the problem I am having:
#include <stdio.h>
#include <iostream>
template<std::size_t U, std::size_t V>
void func2(int (&twoDArrayA)[U][V], const int shift){
const int length = 1 << shift;
int twoDArrayB[length][length]; //Successful
}
//template<std::size_t A> <-- Tried to solve the problem by adding this
void func1(const int shift){
const int length = 1 << shift;
int twoDArrayA[length][length]; //Failed
func2(twoDArrayA,shift);
}
int main() {
const int shift = 3;
func1(shift);
}
Error message:
error: no matching function for call to 'func2(int [length][length], const int&)'
template argument deduction/substitution failed:
variable-sized array type 'int' is not a valid template argument
I thought it is because of the use of the template before the func2, so I tried to do the same thing on func1. The attempt of making the call to func1 fails instead. Error message:
error: no matching function for call to 'func1(const int&)'
template argument deduction/substitution failed:
couldn't deduce template parameter 'A'
Is there any way I can pass such an argument as twoDArrayA to func2?
func2 is failing to deduce the array size because it isn't known at compile time; length is being decided at runtime based on the argument you pass to func1. For the pass-by-reference to work with template arguments and deduction, you will need to have a 2D array with defined size at compile time, for example, int arr[8][8].
It looks like the code you're working on wants to decide the array size in func1 based on shift and then pass that array to func2. You might consider designing func2 to take an int** and then access it as you would a 2D array, based on the result of 1<<shift:
void func2(int** twoDArrayA, const int shift) {
const int length = 1 << shift;
int last_item = twoDArrayA[length-1][length-1]
}
You might also find some more helpful resources here!
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).
Consider this code:
constexpr int TEN = 10;
template < const int& >
struct Object { };
template < const int& II >
void test(Object<II>) { }
Then the calls:
test<TEN>(Object<TEN>{}); // passes
test(Object<TEN>{}); // FAILS
The second call fails to compile with error message:
error: no matching function for call to ‘test(Object<TEN>)
note: candidate: template<const int& II> void test(Object<II>)
note: template argument deduction/substitution failed:
note: couldn't deduce template parameter ‘II’
The question is why? Is it according to the standard?
And the more important question is: how can I workaround this? That is: how can I help the compiler to deduce the const int& template parameter?
In the real code instead of int I have more complex literal type, so I do need the const&. Thus I can't just "use int instead of const int&".
I am using gcc-7.0.1 (the snapshot) and I am getting the same error with options -std=c++11, -std=c++14, -std=c++17.
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.