Resolve variadic argument to function pointer - c++

Windows 10, Visual Studio 2019, C++17:
Compile error:
cannot convert argument 2 from 'int (__cdecl *)(int)' to '...'
////////////////////////////////////////////////////////////////////
// This is the templated function that becomes a variadic argument
//
template <typename siz>
int func(siz size)
{
// ...
// ...
return 0;
}
///////////////////////////////////////////////////////////
// This is the function that uses variadic arguments
//
int usefunc(int option, ...)
{
// ...
// ...
return 0;
}
int main()
{
int result;
result = usefunc(0, func); // ** int usefunc(int,...)': cannot convert argument 2 from 'int (__cdecl *)(int)' to '...' **
// Context does not allow for disambiguation of overloaded function
return result;
}
Without the template (int func(int size) ) the code compiles ok. How do I modify this to make the compiler understand the variadic argument?

The issue is func is being treated as a function pointer, but pointers to template functions are not allowed in C++.
You need to specify the type you plan to use when you reference func, like:
result = usefunc(0, func<int>);
You can use decltype to reference the type of a variable, to be a little more flexible:
result = usefunc(0, func<decltype(result)>);

Related

Passing function into function with std::function and template argument

I am trying to pass a pointer to the predicate function into the Foo and Bar functions.
The Bar function works correctly, but the Foo function raises a compile-time error:
error: no matching function for call to Foo<int>(bool (&)(int))
Why does the compiler raise an error?
Is there any difference between Foo's and Bar's template arguments types after Args' unpacking?
#include <functional>
bool predicate(int a) {
return (a > 5);
}
// sizeof...(Args) == 1 and I suppose it is int
template<typename... Args>
void Foo(std::function<bool(Args...)> predicate) {
// clang: note: candidate template ignored:
// could not match 'function<bool (int, type-parameter-0-0...)>'
// against 'bool (*)(int)'
}
template<typename Args>
void Bar(std::function<bool(Args)> predicate) {
}
int main(int argc, char const *argv[]) {
// gcc: error: no matching function for call to
// 'Foo<int>(bool (&)(int))'
Foo<int>(predicate);
Bar<int>(predicate);
return 0;
}
See Compiler Explorer for a live example.
I also tried to change the Foo function a little and it works somehow:
template<typename... Args>
void Foo(bool(*predicate)(Args...)) {
std::function<bool(Args...)> func(predicate);
}
I want to have std::function type argument in the Foo function, but I don't know how to do it
The error is because the exact type of std::function is not same as predicate. To get around this, you can explicitly call the constructor of std::function:
int main() {
Foo<int>( std::function<bool(int){predicate} );
//OR
Foo<int>( {predicate} );
return 0;
}

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).

Template argument deduction/substitution failed with lambda as function pointer

I'm wondering why in the following code the compiler is unable to use lambda as the argument for function foo() (template argument deduction/substitution failed), while a simple function works:
template<class ...Args>
void foo(int (*)(Args...))
{
}
int bar(int)
{
return 0;
}
int main() {
//foo([](int) { return 0; }); // error
foo(bar);
return 0;
}
The intel compiler (version 18.0.3 )
template.cxx(12): error: no instance of function template "foo" matches the argument list
argument types are: (lambda [](int)->int)
foo([](int) { return 0; }); // error
^
template.cxx(2): note: this candidate was rejected because at least one template argument could not be deduced
void foo(int (*)(Args...))
Any ideas?
Template argument deduction doesn't consider implicit conversion.
Type deduction does not consider implicit conversions (other than type adjustments listed above): that's the job for overload resolution, which happens later.
You can convert the lambda to function pointer explicitly, e.g. you can use static_cast,
foo(static_cast<int(*)(int)>([](int) { return 0; }));
or operator+,
foo(+[](int) { return 0; });

Error in using template for function

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.)

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.