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;
}
Related
While exploring templates in C++, I stumbled upon the example in the following code:
#include <iostream>
#include <functional>
template <typename T>
void call(std::function<void(T)> f, T v)
{
f(v);
}
int main(int argc, char const *argv[])
{
auto foo = [](int i) {
std::cout << i << std::endl;
};
call(foo, 1);
return 0;
}
To compile this program, I am using the GNU C++ Compiler g++:
$ g++ --version // g++ (Ubuntu 6.5.0-1ubuntu1~16.04) 6.5.0 20181026
After compiling for C++11, I get the following error:
$ g++ -std=c++11 template_example_1.cpp -Wall
template_example_1.cpp: In function ‘int main(int, const char**)’:
template_example_1.cpp:15:16: error: no matching function for call to ‘call(main(int, const char**)::<lambda(int)>&, int)’
call(foo, 1);
^
template_example_1.cpp:5:6: note: candidate: template<class T> void call(std::function<void(T)>, T)
void call(std::function<void(T)> f, T v)
^~~~
template_example_1.cpp:5:6: note: template argument deduction/substitution failed:
template_example_1.cpp:15:16: note: ‘main(int, const char**)::<lambda(int)>’ is not derived from ‘std::function<void(T)>’
call(foo, 1);
^
(same for C++14 and C++17)
From the compiler error and notes I understand that the compiler failed to deduce the type of the lambda, since it cannot be matched against std::function.
Looking at previous questions (1, 2, 3, and 4) regarding this error, I am still confused about it.
As pointed out in answers from questions 3 and 4, this error can be fixed by explicitly specifying the template argument, like so:
int main(int argc, char const *argv[])
{
...
call<int>(foo, 1); // <-- specify template argument type
// call<double>(foo, 1) // <-- works! Why?
return 0;
}
However, when I use other types instead of int, like double, float, char, or bool, it works as well, which got me more confused.
So, my questions are as follow:
Why does it work when I explicitly specify int (and others) as the template argument?
Is there a more general way to solve this?
A std::function is not a lambda, and a lambda is not a std::function.
A lambda is an anonymous type with an operator() and some other minor utility. Your:
auto foo = [](int i) {
std::cout << i << std::endl;
};
is shorthand for
struct __anonymous__type__you__cannot__name__ {
void operator()(int i) {
std::cout << i << std::endl;
}
};
__anonymous__type__you__cannot__name__ foo;
very roughly (there are actual convert-to-function pointer and some other noise I won't cover).
But, note that it does not inherit from std::function<void(int)>.
A lambda won't deduce the template parameters of a std::function because they are unrelated types. Template type deduction is exact pattern matching against types of arguments passed and their base classes. It does not attempt to use conversion of any kind.
A std::function<R(Args...)> is a type that can store anything copyable that can be invoked with values compatible with Args... and returns something compatible with R.
So std::function<void(char)> can store anything that can be invoked with a char. As int functions can be invoked with a char, that works.
Try it:
void some_func( int x ) {
std::cout << x << "\n";
}
int main() {
some_func('a');
some_func(3.14);
}
std::function does that some conversion from its signature to the callable stored within it.
The simplest solution is:
template <class F, class T>
void call(F f, T v) {
f(v);
}
now, in extremely rare cases, you actually need the signature. You can do this in c++17:
template<class T>
void call(std::function<void(T)> f, T v) {
f(v);
}
template<class F, class T>
void call(F f_in, T v) {
std::function f = std::forward<F>(f_in);
call(std::move(f), std::forward<T>(v));
}
Finally, your call is a crippled version of std::invoke from c++17. Consider using it; if not, use backported versions.
Here is my code:
bool test(){
return true;
}
template<int asd[], bool T = test()>
void evenprocessor(){
std::cout<<"this is called"<<std::endl;
};
int asd[] = {1,2,3};
int main(int argc, char** argv) {
evenprocessor<asd>();
return 0;
}
I was doing some testings for sfinae, I am curious if something like this is possible. Evaluating a function once the template is called. I get an error stating that no matching function to call to evenprocessor.
Am I doing something wrong or it's impossible to evaluate a function if it's used inside a function or template parameter? Something like this:
template<int asd[]>
void evenprocessor(char(*)[test()]){
std::cout<<"this is called"<<std::endl;
};
int asd[] = {1,2,3};
int main(int argc, char** argv) {
evenprocessor<asd>();
return 0;
}
I get an error stating that says variable or field evenprocessor declared void. Why is it declared void?
The first one did not compile for me. I had to change it to this, compiling for C++11. Declare the test() function as constexpr to let the compiler know that it can be evaluated at compile time.
Evaluating a function once the template is called.
You need to make sure that the function can be evaluated at compile time as mentioned before. Otherwise you cannot compile the program.
#include <iostream>
constexpr bool test(){
return true;
}
template<int asd[], bool T = test()>
void evenprocessor(){
std::cout << "this is called" << std::endl;
};
int asd[] = {1,2,3};
int main(int argc, char** argv) {
evenprocessor<asd>();
return 0;
}
The second code example does not make sense to me. What are you trying to achieve?
There are several errors I see.
The parameter name is absent.
The piece of code in the function operator brackets is expected to be a lambda function. What you probably were trying to achieve is to point to an array that holds one element of type bool with value true. Review your requirement.
A template non-type argument must be a converted constant expression. An invocation of a function "other than a constexpr constructor for a literal class, a constexpr function, or an implicit invocation of a trivial destructor" is not a core constant expression ([expr.const]). In your cast, test() is not a core constant expression because it is not constexpr. The compile error indicates this pretty clearly:
clang's error:
main.cpp:8:30: error: non-type template argument is not a constant expression
template<int asd[], bool T = test()>
^~~~~~
gcc's error:
main.cpp:9:6: note: template argument deduction/substitution failed:
main.cpp:8:34: error: call to non-constexpr function 'bool test()'
template<int asd[], bool T = test()>
^
Simply fix test:
constexpr bool test() {
return true;
}
The second example fails for the same reason. Array-bounds must be core constant expressions as well. If you fixed test() to be constexpr, then your code would fail for the obvious reason that:
main.cpp:16:5: error: no matching function for call to 'evenprocessor'
evenprocessor<asd>();
^~~~~~~~~~~~~~~~~~
main.cpp:9:6: note: candidate function template not viable: requires 1 argument, but 0 were provided
void evenprocessor(char(*)[test()]){
^
Oh right, gotta pass in something:
evenprocessor<asd>(nullptr);
Now everything compiles.
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.
I have a compile error when using std::function in a templated member function, the following code is a simple example:
#include <functional>
#include <memory>
using std::function;
using std::bind;
using std::shared_ptr;
class Test {
public:
template <typename T>
void setCallback(function<void (T, int)> cb);
};
template <typename T>
void Test::setCallback(function<void (T, int)> cb)
{
// do nothing
}
class TestA {
public:
void testa(int a, int b) { }
};
int main()
{
TestA testA;
Test test;
test.setCallback(bind(&TestA::testa, &testA, std::placeholders::_1, std::placeholders::_2));
return 0;
}
And come with the following compile error:
testtemplate.cpp: In function ‘int main()’:
testtemplate.cpp:29:92: error: no matching function for call to
‘Test::setCallback(std::_Bind_helper)(int, int),
TestA, const std::_Placeholder<1>&, const
std::_Placeholder<2>&>::type)’
testtemplate.cpp:29:92: note: candidate is: testtemplate.cpp:10:7:
note: template void Test::setCallback(std::function)
testtemplate.cpp:10:7: note: template argument
deduction/substitution failed:
testtemplate.cpp:29:92: note: ‘std::_Bind(TestA*, std::_Placeholder<1>,
std::_Placeholder<2>)>’ is not derived from ‘std::function’
I'm using C++11 and g++ 4.7
To figure out the problem let separate statements:
auto f = bind(&TestA::testa, &testA, _1, _2); // OK
test.setCallback(f); // <<--- Error is here
setCallback needs to know type of T and it can't deduce it from f, so give it a type
test.setCallback<TYPE>(f); // TYPE: int, float, a class, ...
You can make type deduction work with some variant of:
template<typename CALLBACK>
void setCallback(CALLBACK cb) {
typedef CALLBACK::first_argument_type T;
static_assert(is_same_type<CALLBACK,function<void(T,int)>>::value);
...
}
This way CALLBACK can be determined by looking at the argument. It might get into trouble if bind doesn't actually return a std::function but rather something that can be cast as one. I'm not sure.
I have a templated C++ class with a further template on one of its member functions.
I am calling it in two places in my code, one of them works, the other generates a very confusing error which boils down to the sample code below:
#include <memory>
template <unsigned char N>
struct Foo
{
template <typename OtherFoo, unsigned X>
void do_work (
const OtherFoo * __restrict,
float,
Foo * __restrict
)
const
{
}
};
struct Bar
{
std :: unique_ptr <Foo<0>> foo_0;
std :: unique_ptr <Foo<1>> foo_1;
std :: unique_ptr <Foo<2>> foo_2;
void run (float);
template <typename FOO>
void run (std :: unique_ptr <FOO> & foo, float x)
{
FOO out;
foo -> template do_work <123> (foo_2.get(), x, &out);
}
};
void Bar :: run (float x)
{
if (foo_0)
run (foo_0, x);
else
run (foo_1, x);
}
int main ()
{
Bar bar;
bar .run (1.23);
}
The error message is quite straightforward, but apparently wrong.
temp.cpp: In member function ‘void Bar::run(std::unique_ptr<FOO>&, float) [with FOO = Foo<0u>]’:
temp.cpp:61:16: instantiated from here
temp.cpp:54:3: error: no matching function for call to ‘Foo<0u>::do_work(Foo<2u>*, float&, Foo<0u>*)’
temp.cpp: In member function ‘void Bar::run(std::unique_ptr<FOO>&, float) [with FOO = Foo<1u>]’:
temp.cpp:63:16: instantiated from here
temp.cpp:54:3: error: no matching function for call to ‘Foo<1u>::do_work(Foo<2u>*, float&, Foo<1u>*)’
Let's see, no matching function for call to Foo<1u>::do_work(Foo<2u>*, float&, Foo<1u>*) ...? No, that to me looks EXACTLY like a valid instantiation of Foo::do_work.
Is the compiler wrong? (gcc 4.5.1 on ubuntu 12.04) What's especially weird is that this code does compile in what appears to be an equivalent invocation elsewhere in the code (the full thing has rather too many dependencies to be meaningfully reproduced here).
You should change the order of your template parameters for the do_work<>() function template, or your instantiation will indeed be incorrect:
// template<typename OtherFoo, unsigned X> // This order is not appropriate.
// Let template parameters that
// cannot be deduced come first...
template<unsigned X, typename OtherFoo>
// ^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
// THIS FIRST THEN THIS
void do_work(const OtherFoo* __restrict, float, Foo* __restrict) const
{
}
That is because in the following function call you are providing an explicit argument for the first template parameter:
foo->template do_work<123>(foo_2.get(), x, &out);