for a demo code
#include <iostream>
#include <map>
#include <vector>
using namespace std;
typedef struct Student
{
public:
Student(){}
~Student(){}
static void print(int a,int b){printf("age is a\n");}
}Student;
int main(){
void (*p)(int, int) = &Student::print;
vector<void(*)(int,int)> tt;
tt.push_back(p);
tt[0](1,1);
return 0;
}
when I want to make the void(*)(int,int) as a struct member, like
struct void_func_st{
void(*)(int,int) f;
int a;
};
the code is wrong. I don't know whether the struct could be made actually as I'm not familiar with how the void(*)(...) works. Or I just didn't get the right way to make void(*)(...) as a struct member. Can anyone give some advice?
It would be (as you do for local variable p in main)
void(*f)(int,int);
As note, typedef/using or some "wrapper" might help to have more regular syntax, for example:
using bin_func = void(int, int);
bin_func* f2;
std::add_pointer_t<void(int, int)> f3;
std::type_identity_t<void(int, int)>* f4;
Use std::function and forget about the confusing function pointer syntax:
struct void_func_st {
std::function<void(int,int)>; f;
int a;
};
Even better, introduce a nice alias for it:
using MyFunction = std::function<void(int,int)>;
Related
I have a namespace, N0, that has sub-namespaces including N1. The calling code only knows about the outer namespace. I'd like to write a function in the outer namespace that returns a std::unique_ptr<N1::T> where that result is consumed elsewhere in N0. However, the caller shouldn't know about N1. What I'd like to do is something like:
// N0.h
namespace N0 {
typename T; // This isn't real C++.
std::unique_ptr<T> foo();
void bar(std::unique_ptr<T>&&);
}
// N0.cpp
#include "N1.h" // Get N1::T
namespace N0 {
typedef N1::T T;
...
}
That is, I'd like to expose a type that the caller can't see but internally I'd like to actually use a type in a different namespace. This way elsewhere someone could just forward-declare namespace N0 { class T; } without having to know that T is actually in N1.
I could move T itself into N0, but it really belongs in N1.
I could wrap T with a dummy class in N0, but that's ugly, and the pointer should basically do that.
I could probably make a class N0::T that subclasses N1::T, but that seems icky too.
Is there no way for N0 to forward declare that "I have a type and you don't need to know what it is" and have that type actually be in a different namespace? Put another way: Why is class C; class C{}; legal but class C; typedef int C; is illegal? (Likewise class C; using C = int; or typedef C; typedef int C;.) They seem fundamentally the same to me and I can't think of a clever template trick to get around it. The only difference I can think of is that the typedef version wouldn't be subject to Koenig lookup.
I mean you could do this:
// N0.h
namespace N0 {
std::unique_ptr<T> foo();
void bar(std::unique_ptr<T>&&);
}
// N0.cpp
namespace N0 {
typedef N1::T t;
}
#include "N0.h"
namespace N0 {
// whatever...
}
In the situation you have described, the foo should be implemented as a template function:
namespace N0 {
template <typename T>
std::unique_ptr<T> foo(){...};
template <typename T>
void bar(std::unique_ptr<T>&&){...};
}
And you should using a wrap/overload function to do the final trick:
namespace N0 {
std::unique_ptr<N1::T> foo() { return foo<N1::T>(); }
//for bar there is no need to wrap, cause the T could be resolved by parameters.
}
Here's the best I've come up with, which seems to work. I still feel like there should be a way to not use "tricks" to make N1::T fully hidden from callers:
// N0.h
#pragma once
#include <memory>
namespace N0 {
struct OpaqueObject { virtual ~OpaqueObject() {} };
std::unique_ptr<OpaqueObject> foo();
void bar(std::unique_ptr<OpaqueObject>&&);
}
//N0.cpp
#include "N1.h"
namespace N0 {
std::unique_ptr<OpaqueObject> foo() { return std::unique_ptr<N1::T>(new N1::T()); }
void bar(std::unique_ptr<OpaqueObject> &&) {}
}
// N1.h
#pragma once
#include "N0.h"
namespace N1 {
class T : public N0::OpaqueObject {};
}
// test.cpp
#include "N0.h"
int main() {
auto x = N0::foo();
N0::bar(std::move(x));
}
I am trying to call pointer to a void * function inside the main method and the compiler is saying assigning to 'funcptr<g>' from incompatible type 'void *(void *). hello function is actually an argument to pthread_create function. That's why it is void * function. How can I create a function pointer to a void * function?
#include <iostream>
#include <pthread.h>
using namespace std;
template<typename T>
using funcptr = void (*T::*)(void *); // I think it is wrong here.
class m {
public:
template <typename T>
struct my_struct {
funcptr<T> ptr;
};
};
class g {
public:
static void *hello(void *);
};
int main() {
struct m::my_struct<g> h;
h.ptr = g::hello; // Error here
return 0;
}
How can I create a function pointer to a void * function?
hello is not a member function, but it's a static function.
So your funcptr should be as follows:
// No template needed.
using funcptr = void* (*)(void *)
Note that hello is declared with static, meaning that it's no longer a member function to g.
Static members of a class are not associated with the objects of the class.
So using void (*T::*)(void *) to cull non-member functions is incorrect.
If you're allowed to use a compiler that supports C++11, you don't even need to manually deduct its type anymore, using decltype:
// decltype deducts its exact type for you.
using funcptr = decltype(&g::hello);
class m
{
public:
struct my_struct
{
funcptr ptr;
};
};
FYI, since hello does not have its definition, you might encounter a linkage error. To prevent that, I assumed that there's some implementation inside:
static void *hello(void *)
{
// Meaningless, but..
return nullptr;
}
if you're using C++11, you can use std::function<> which just bothers about the return type and parameters of the function and not where they are defined and what are its type.
Here is the code using std::function<>
#include <iostream>
#include <functional>
#include <pthread.h>
using namespace std;
class m {
public:
template <typename T>
struct my_struct {
function<void*(void*)> ptr;
};
};
class g {
public:
static void *hello(void *) {
cout<<"Hello.."<<endl;
}
};
int main() {
struct m::my_struct<g> h;
h.ptr = g::hello;
h.ptr(nullptr);
return 0;
}
is there any way to define an object in a way similar to the line below???
template<typename T>
struct A {
T *data;
//...
typedef T data_type;
};
int main() {
A<int>::data_type a; // ok
A<int> obj;
obj.data_type b; // <-- is it possible to do something like this??
}
Thanks!
Massimo
You can use decltype on expressions. The code for your case would be:
decltype(obj)::data_type b;
From C++11 onwards it is possible:
decltype(obj) is evaluated at compile-time and is the type of obj. It can be used whenever a type is used.
So you could write decltype(obj)::data_type b;
decltype is a keyword and is particularly useful in generic programming.
This seems to work fine; use decltype() for c++11; you can try typeof() pre c++11
typeof() in gcc: https://gcc.gnu.org/onlinedocs/gcc/Typeof.html
#include <iostream>
using namespace std;
template<typename T>
struct A {
T *data;
//...
typedef T data_type;
};
int main() {
A<int>::data_type a; // ok
A<int> obj;
decltype(obj)::data_type b; // <-- is it possible to do something like this??
}
I use BOOST_PHOENIX_ADAPT_FUNCTION all the time in Spirit. I'd like to be able to adapt member functions for all of the same reason. However, I get compile errors if I do something like this:
struct A { int foo(int i) { return 5*i; }};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, &A::foo, 2)
Is there an easy way to adapt a member function? Note that I can't just store a bind expression in an auto because I am on VC2008. How come it doesn't just work like in bind and function?
Thanks,
Mike
The BOOST_PHOENIX_ADAPT_FUNCTION(RETURN,LAZY_NAME,FUNC,N)is really simple. It just creates a functor with a templated operator() that returns RETURN and has N template parameters. In its body it simply invokes FUNC(PARAMETERS...). But &A::foo is not directly callable, and so your error occurs. You can use:
BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
Running on Coliru
#include <iostream>
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <boost/mem_fn.hpp>
struct A {
A(int f) : f_(f) {}
int foo(int i) {
return f_*i;
}
private:
int f_;
};
BOOST_PHOENIX_ADAPT_FUNCTION(int,AFoo,boost::mem_fn(&A::foo),2)
int main() {
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
A instance(5);
std::cout << AFoo(arg1,arg2)(&instance, 2) << std::endl;
}
Starting with the simplest:
How come it doesn't just work like in bind and function?
Because the macro is designed for functions, not member functions. Pointer-to-member-functions are very different from function pointers, so that's the end of the road.
In your example, A::foo doesn't actually need to be an instance method (non-static member function), so just add static (and an implicit parameter) and be done:
struct A {
static int foo(int i) {
return 5*i;
}
};
BOOST_PHOENIX_ADAPT_FUNCTION(int, AFoo, A::foo, 1)
Let's assume, though, that you did want to have the non-static member function. For this reason, let's add a little state to the A type:
struct A {
A(int f) : f_(f) {}
int foo(int i) { return f_*i; }
private:
int f_;
};
Phoenix provides the following approaches to create lazy actors calling member functions:
use the ->* operator. This leads to slightly obscure syntax:
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7); // direct == 63
alternatively, you can use a bind expression (note: boost::phoenix::bind here!), which might just be what you were looking for:
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
Now, of course, you might be looking to assign the lazy functor to a variable. In that respect, I can only recommend BOOST_AUTO:
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
Which works like a charm.
Full C++03 Sample
See it Live on Coliru
struct A {
A(int f) : f_(f) {}
int foo(int i) {
return f_*i;
}
private:
int f_;
};
#include <boost/phoenix.hpp>
#include <boost/phoenix/function.hpp>
#include <cassert>
int main() {
using namespace boost::phoenix;
using namespace boost::phoenix::arg_names;
A instance(9);
int direct = (arg1->*&A::foo)(arg2)
(&instance, 7);
int with_bind = bind(&A::foo, arg1, arg2)
(&instance, 7);
assert(direct == with_bind);
BOOST_AUTO(afoo, (arg1->*&A::foo)(arg2));
return afoo(&instance, 2);
}
I'm in the process of learning boost::lambda and I've managed to create a situation that I can't resolve with what I know so far.
Apparently in the bowels of boost::lambda, the following example causes the attempted instantiation of abstract class AbstractFoo, and prevents the lambda expression from compiling. The problem is that I don't know why it is trying to instantiate it so I cant try to work around it.
Any boost::lambda experts that can:
give me a clue as to why this is happening?
suggest a work around?
Example:
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
struct AbstractFoo
{
typedef boost::shared_ptr<AbstractFoo> Ptr;
virtual int it() const = 0;
};
struct Bar : public AbstractFoo
{
typedef boost::shared_ptr<Bar> Ptr;
virtual int it() const { return 3; }
};
typedef AbstractFoo Foo; // Comment this out
//typedef Bar Foo; // and this in to make this example compilable
int main()
{
namespace bll = boost::lambda;
boost::function< bool (const Foo::Ptr &)> func;
func = (bll::protect(bll::bind( &Foo::it, *bll::_1))(bll::_1) == 3);
return 0;
}
This fails to compile (on gcc 4.4.3, boost 1_40) with a monster template error the important part of which seems to be:
error: cannot declare field
‘boost::tuples::cons<AbstractFoo,boost::tuples::null_type>::head’
to be of abstract type ‘AbstractFoo’
because the following virtual functions are pure within ‘AbstractFoo’:
virtual int AbstractFoo::it() const
As you discovered, you can not do that, because the object needs to be copied, but in this case it can not be instantiated because it contains a pure virtual method. The simplest solution is to pass it using a pointer :
#include <boost/lambda/bind.hpp>
#include <boost/lambda/lambda.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/function.hpp>
#include <iostream>
struct AbstractFoo
{
typedef boost::shared_ptr<AbstractFoo> Ptr;
virtual int it() const = 0;
};
struct Bar : public AbstractFoo
{
typedef boost::shared_ptr<Bar> Ptr;
virtual int it() const { return 3; }
};
typedef AbstractFoo Foo; // Comment this out
//typedef Bar Foo; // and this in to make this example compilable
int main()
{
namespace bll = boost::lambda;
boost::function< bool ( const Foo * )> func;
func = ( bll::protect( bll::bind( &Foo::it, bll::_1 ) )( bll::_1 ) == 3);
//func = bll::bind( &Foo::it, bll::_1 );
Foo::Ptr p( new Bar );
std::cout << std::boolalpha << func( p.get() ) << std::endl;
}
To be more precise, this :
*bll::_1
needs to instantiate and copy object of type AbstractFoo
Riffing off of JVo's answer, the following works around the issue:
func3 = (bll::protect(bll::bind( &Foo::it,
bll::bind( &Foo::Ptr::get,
bll::_1 ))) (bll::_1) == 2);
where
bll::bind( &Foo::Ptr::get, bll::_1)
Pulls out the pointer so that the place holder is not dereffed in line.
From the comments suggesting compiling without error in VS with Boost 1_47 I might guess that the issue has since been fixed in boost, and that it was a sort of bug.