I have template function change that takes a function that takes int and returns an object of type A. So I thought I can use the constructor of A
class A {
int y;
public:
explicit A(int y) : y(2 * y) {
}
};
class B {
A x;
public:
B(int x) : x(x) {
}
template<typename F>
void change(int y, F func) {
x = func(y);
}
};
int main(void) {
B b(7);
b.change(88, A()); // << here
return 0;
}
But the compiler says no matching function for call to ‘A::A()’
How can I make it works?
You can't pass a constructor as a parameter like you are attempting. The C++ standard is very strict on not allowing the memory address of a constructor to be taken.
When you call change(88, A()), you are actually constructing a temp A object (which the compiler should not allow since A does not have a default constructor) and then you are passing that object to the parameter of change(). The compiler is correct to complain, since A does not define an operator()(int) to satisfy the call to func(y) when called in an A object.
To make this work, you need to create a separate function that constructs the A object, and then pass that function to change(), eg:
A createA(int y)
{
return A(y);
}
int main(void) {
B b(7);
b.change(88, createA);
return 0;
}
Related
I'd want to use a function pointer in my template argument list. I do miss something of B even I am writing int in full main of both A and B. I have a class X.h like so, don't know which one it is now causing the error.
struct X
{
int fun(int a)
{
return a;
}
template<typename A, typename B>
A func(int x, B(*f)(int))
{
A i = 10;
return i + f(x);
}
};
and I like to use it in main.cpp
int main()
{
X d;
std::cout << d.func<int, int>(10, &X::fun) << "\n";
return 0;
}
The error is No instance of func matches the argument list...
The problem is that the argument &X::fun is of type int (X::*)(int) while the parameter f is of type int(*)(int) (when B = int) and there is no implicit conversion from the former to the latter and hence the error.
To solve this you can change the parameter f to be of type B(X::*)(int) as shown below. Note that the syntax for making a call using member function pointer is different for making a call to a free function.
With C++17, we can use std::invoke.
struct X
{
int fun(int a)
{
return a;
}
template<typename A, typename B>
//------------------vvvv-------------->added this X:: here
A func(int x, B(X::*f)(int))
{
A i = 10;
//-----------------vvvvvvvvvv-------->this is the syntax to call using member function pointer
return i + (this->*f)(x);
//return std::invoke(f, this, x); //use std::invoke with C++17
}
};
int main()
{
X d;
std::cout << d.func<int, int>(10, &X::fun) << "\n"; //works now
return 0;
}
Working demo
Is there a nice way to have a non static value as default argument in a function? I've seen some older responses to the same question which always end up in explicitly writing out the overload. Is this still necessary in C++17?
What I'd like to do is do something akin to
class C {
const int N; //Initialized in constructor
void foo(int x = this->N){
//do something
}
}
instead of having to write
class C {
const int N; //Initialized in constructor
void foo(){
foo(N);
}
void foo(int x){
//do something
}
}
which makes the purpose of the overload less obvious.
One relatively elegant way (in my opinion) would be to use std::optional to accept the argument, and if no argument was provided, use the default from the object:
class C {
const int N_; // Initialized in constructor
public:
C(int x) :N_(x) {}
void foo(std::optional<int> x = std::nullopt) {
std::cout << x.value_or(N_) << std::endl;
}
};
int main() {
C c(7);
c.foo();
c.foo(0);
}
You can find the full explanation of what works/doesn't work in section 11.3.6 of the standard. Subsection 9 describes member access (excerpt):
A non-static member shall not appear in a default argument unless it
appears as the id-expressionof a class member access expression
(8.5.1.5) or unless it is used to form a pointer to member
(8.5.2.1).[Example:The declaration of X::mem1()in the following example
is ill-formed because no object is supplied for the non-static
memberX::a used as an initializer.
int b;
class X {
int a;
int mem1(int i = a);// error: non-static memberaused as default argument
int mem2(int i = b);// OK; useX::b
static int b;
};
We have a structure that accepts C function pointers:
int one(int x)
{
}
int two(int x)
{
}
struct Cstruct
{
int (*fn1)(int);
int (*fn2)(int);
};
Now I have a C++ class that has below methods:
class A
{
public:
int one(int x)
{
}
int two(int x)
{
}
int three(int x)
{
struct Cstruct cstr = {&this->one, &this->two};
}
};
While trying to initialize class A methods address to a instance of Cstruct compiler is giving error of an invalid conversion?
How can I assign the Class member function address to Cstruct?
You cannot do it, because C++ pointer to a non-static member function is not compatible with a non-member function pointer type. This is because member functions require an additional argument - the object on which the member function needs to be called, which becomes this pointer inside the invocation.
If you make your member functions static, your code would compile. However, it would not necessarily do what you want to achieve, because one and two have no access to other non-static members of A.
A trick to passing member functions to C functions requires passing an additional void* pointer with the "registration" record, and having C code pass it back to your static callback functions:
struct Cstruct
{
void *context; // Add this field
int (*fn1)(void*, int);
int (*fn2)(void*, int);
};
class A
{
public:
static int oneWrap(void* ptr, int x)
{
return static_cast<A*>(ptr)->one(x);
}
static int twoWrap(void* ptr, int x)
{
return static_cast<A*>(ptr)->two(x);
}
int one(int x)
{
}
int two(int x)
{
}
int three(int x)
{
struct Cstruct cstr = {this, &this->oneWrap, &this->twoWrap};
}
};
C code would need to pass the value of context to fn1 and fn2:
cs.fn1(cs.context, 123);
cs.fn2(cs.context, 456);
I would like to pass a templated function args for class and a method of that class to call. The method has arguments as well as a return value.
Here is what I have so far. I believe I'm getting a little tripped up on the templatized function syntax:
bar.h
class Bar {
public:
Bar();
int FuncBar(int arg1);
}
foo.h
template<typename A, int (A::*Method)()>
int FuncTemplate(A* a, int bar_arg1) {
....
return a->Method(bar_arg1)
}
class Foo {
public:
explicit Foo(Bar* bar);
private:
void FuncFoo();
Bar* bar_;
}
foo.cc
Foo::Foo(Bar bar) : bar_(bar) {};
void Foo::FuncFoo() {
...
int bar_arg1 = 0;
FuncTemplate<Bar, &(*bar_)::FuncBar>(bar_, bar_arg1);
}
You need to use int (A::*Method)(int) as the function pointer type since the member function expects an int as an argument.
Also, the call to the member function needs to be (a->*Method)(bar_arg1). The syntax for calling member function using a member function is not very intuitive.
template<typename A, int (A::*Method)(int)>
int FuncTemplate(A* a, int bar_arg1) {
....
return (a->*Method)(bar_arg1)
}
Also, you need to use &Bar::FuncBar to get a pointer to the member function, not &(*bar_)::FuncBar.
void Foo::FuncFoo() {
int bar_arg1 = 0;
FuncTemplate<Bar, &Bar::FuncBar>(bar_, bar_arg1);
// ^^^^^^^^^^^^^
}
This question already has answers here:
How do you pass a member function pointer?
(6 answers)
Closed 9 years ago.
I have a class
class A{
A(/*constructor arguments*/);
double MethA(double);
};
And I want to pass the method MethA in a function that takes a pointer to a function :
double function(double (*f)(double), double x){
return f(x);
}
So what I'm doing is to call
A a(/*constructor arguments*/);
function(a.MethA,1.0);
but it doesn't compile.
I'm pretty sure that this question is answered somewhere else, but I couldn't find where because I'm not sure that the terminology I use is correct. Am I trying to pass a pointer on a class method as a function argument ? Or, to pass a function pointer as a member of a class... I'm confused :-(
When you need to use a pointer to member function, you need to pass two separate things:
what member function to call and
what instance to call it on.
In C++, you can't combine them in one construct, like you want to:
A a;
bar(a.foo);
is not valid C++.
Instead, you have to do this:
A a;
bar(a, &A::foo)
And declare and implement bar() accordingly:
void bar(A &a, void (A::*method)()) {
a.*method();
}
See Arkadiy's answer if you want to see how to properly use member function pointers.
BUT
As requested in the comments: if the compiler you are using supports lambdas (some without full C++11 do). You can do something like the following, which looks more like the syntax you are attempting to use.
Your definition for function changes to something like:
template <typename F>
double function(F f, double x){
return f(x);
};
a function template that accepts a parameter that is callable with a double.
At your call-site you do this:
A a(/*constructor arguments*/);
function([&](double x){return a.MethA(x);},1.0);
That generates a function object in-place that is bound to your class instance a by reference.
The template can be made fully typesafe with some magic in <type_traits>, but as-is it will give you template spew if you pass something very wrong.
It has to be a static function!
#include <iostream>
#include <cassert>
class A {
public:
static double MethA(double x) { return 5 * x; }
};
typedef double (*ftype)(double);
double function(ftype f) {
assert(f != NULL);
return f(7);
}
int main(int, char**) {
// expect "35\n" on stdout
std::cout << function(A::MethA) << "\n";
}
It has to be static because you can't access any of A's variables without knowing which A object are you refering to! If you need A's non-static member variables, you need to pass a reference to an a into the static function:
#include <iostream>
#include <cassert>
class A {
double fX;
public:
A(double x) : fX(x) { }
double methB(double x) const { return fX * x; }
static double MethB(double x, const A& a) {
return a.methB(x);
}
};
typedef double (*ftype2)(double, const A&);
double function_with_context(ftype2 f, const A& a) {
assert(f != NULL);
return f(7, a);
}
int main(int, char**) {
A a(6);
// expect "42\n" on stdout
std::cout << function_with_context(A::MethB, a) << "\n";
}
But it's sometimes better to use inheritance and polymorphism to achieve this sort of interface:
#include <iostream>
class MyInterface {
public:
virtual double f(double x) const = 0;
};
class A : public MyInterface {
double fX;
public:
A(double x) : fX(x) { }
double f(double x) const {
return fX * x;
}
};
double function(const MyInterface& o) {
return o.f(7);
}
int main(int, char**) {
A a(6);
// expect "42\n" on stdout
std::cout << function(a) << "\n";
}