I need a function which establishes a policy for my class for displaying items. e.g:
SetDisplayPolicy(BOOLEAN_PRED_T f)
This is assuming BOOLEAN_PRED_T is a function-pointer to some boolean predicate type like:
typedef bool (*BOOLEAN_PRED_T) (int);
I'm interested only on e.g: display something when the passed predicate is TRUE, do not display when it's false.
The above example works for functions returning bool and taking an int, but I need a very generic pointer for the SetDisplayPolicy argument, so I thought of UnaryPredicate, but it's boost related. How I can pass a unary predicate to a function in STL/C++? unary_function< bool,T > won't work because I need a bool as return value, but I want to ask the user just for "unary function that returns bool", in the most generic approach.
I thought of deriving my own type as:
template<typename T>
class MyOwnPredicate : public std::unary_function<bool, T>{};
Could that be a good approach?
Turn SetDisplayPolicy into a function template:
template<typename Pred>
void SetDisplayPolicy(Pred &pred)
{
// Depending on what you want exactly, you may want to set a pointer to pred,
// or copy it, etc. You may need to templetize the appropriate field for
// this.
}
Then to use, do:
struct MyPredClass
{
bool operator()(myType a) { /* your code here */ }
};
SetDisplayPolicy(MyPredClass());
In the display code you would then d someting like:
if(myPred(/* whatever */)
Display();
Of course, your functor may need to have a state and you may want its constructor to do stuff, etc. The point is that SetDisplayPolicy doesn't care what you give it (including a function pointer), provided that you can stick a function call onto it and get back a bool.
Edit: And, as csj said, you could inherit from STL's unary_function which does the same thing and will also buy you the two typedefs argument_type and result_type.
You're on the right track since unary_function is intended as a base class. However, note that the first parameter is supposed to be the argument_type and the second is the result_type. Then, all you need to do is implement operator()
template<typename T>
struct MyOwnPredicate : public std::unary_function<T,bool>
{
bool operator () (T value)
{
// do something and return a boolean
}
}
Related
I recently wrote about the function of class member function callbacks. I need to save the callback object and function pointer, then call the function pointer and fill in the appropriate parameters where the callback is needed.
I started out as a form of typedef void (AAA::*Function)(int a, int b);, but when I need to support different parameter lists of member function, I obviously need a dynamic way to implement it.
class AAA
{
public:
int add(int a, int b)
{
return (a + b);
}
};
class BBB
{
public:
void setValue(std::string value)
{
this->value = value;
}
private:
std::string value;
};
class CCC
{
public:
void bind(??? p) // Binding objects and callback functions.
{
this->p = p;
}
template <class... Args>
auto callback(Args&&... args) // Autofill parameter list.
{
return this->p(std::forward<Args>(args)...);
}
private:
??? p; // How is this function pointer implemented?
};
int main()
{
AAA aaa;
BBB bbb;
CCC ccc;
ccc.bind(???(aaa, &AAA::add));
int number = ccc.callback(5, 6);
ccc.bind(???(bbb, &BBB::setValue));
ccc.callback("Hello");
system("pause");
return 0;
}
I don't know how can I implement the function pointer "???".
You basically are asking to have fully dynamicly typed and checked function calls.
To have fully dynamic function calls, you basically have to throw out the C++ function call system.
This is a bad idea, but I'll tell you how to do it.
A dynamicly callable object looks roughly like this:
using dynamic_function = std::function< std::any( std::vector<std::any> ) >
where use use
struct nothing_t {};
when we want to return void.
Then you write machinery that takes an object and a specific signature, and wraps it up.
template<class R, class...Args, class F>
struct dynamic_function_maker {
template<std::size_t...Is>
dynamic_function operator()(std::index_sequence<Is...>, F&& f)const {
return [f=std::forward<F>(f)](std::vector<std::any> args)->std::any {
if (sizeof...(Is) != args.size())
throw std::invalid_argument("Wrong number of arguments");
if constexpr( std::is_same< std::invoke_result_t<F const&, Args... >, void >{} )
{
f( std::any_cast<Args>(args[Is])... );
return nothing_t{};
}
else
{
return f( std::any_cast<Args>(args[Is])... );
}
};
}
dynamic_function operator()(F&& f)const {
return (*this)(std::make_index_sequence<sizeof...(Args)>{}, std::forward<F>(f));
}
};
template<class R, class...Args, class F>
dynamic_function make_dynamic_function(F f){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
next you'll want to deduce signatures of function pointers and the like:
template<class R, class...Args>
dynamic_function make_dynamic_function(R(*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(std::forward<F>(f));
}
template<class Tclass R, class...Args>
dynamic_function make_dynamic_function(T* t, R(T::*f)(Args...)){
return dynamic_function_maker<R,Args...,F>{}(
[t,f](auto&&...args)->decltype(auto){return (t->*f)(decltype(args)(args)...);}
);
}
then after fixing typos above you should be able to solve your original problem.
Again, as someone who can actually write and understand the above code, I strongly advise you not to use it. It is fragile and dangerous.
There is almost never a good reason to store callbacks in places where you don't know what the arguments you are going to call it with.
There should be a different type and instance of CCC for each set of arguments you want to call it with. 99/100 times when people ask this question, they are asking the wrong question.
C++ is a type-safe language. This means that you cannot do exactly what you've outlined in your question. A pointer to a function that takes specific parameters is a different type from a pointer to a function that takes different parameters. This is fundamental to C++.
std::bind can be use to type-erase different types to the same type, but you get a single type at the end, that can be called only with a matching set of parameters (if any). It is not possible to invoke the "underlying" bound function, with its real parameters. That's because the whole purpose of std::bind is to make them disappear, and inaccessible. That's what std::bind is for.
You only have a limited set options to make this work while staying with the bounds and constraints of C++'s type-safety.
Make use of a void *, in some fashion. Actually, don't. Don't do that. That will just cause more problems, and headache.
Have a separate list and classes of callbacks, one list for each set of callbacks that take a specific set of parameters. You must know, at the point of invoking a callback, what parameters you intend to pass. So, just get your callback from the appropriate list.
Make use of std::variant. The type-safe std::variant is C++17 only (but boost has a similar template that's mostly equivalent, and available with older C++ revisions). All your callbacks take a single std::variant parameter, a variant of every possible set of parameters (designated as a std::tuple of them, or some class/struct instance). Each callback will have to decide what to do if it receives a std::variant containing the wrong parameter value.
Alternatively, the std::variant can be a variant of different std::function types, thus shifting the responsibility of type-checking to the caller, instead of each callback.
The bottom line is that C++ is fundamentally a type-safe language; and this is precisely one of the reasons why one would choose to use C++ instead of a different language that does not have the same kind of type-safety.
But being a type-safe language, that means that you have certain limitations when it comes to juggling different types together. Specifically: you can't. Everything in C++ is always, and must be, a single type.
I am trying to do the following, and I am not even sure if it's possible.
I want a function that takes in an arbitrary function pointer to pass it to a different function (I am aware this is a code smell, good software engineering practices are not what I want to discuss right now).
In other words what I am looking for would look like:
void method1(arbitraty pointer p)
{
method2(p);
}
I am not sure if there is a way to declare arbitrary function pointers (the return value is guaranteed to be void but the parameters are arbitrary, both in number and type)
Use template and use SFINAE to enable it only if the type deduced is a function pointer type:
template <typename T, std::enable_if_t<std::is_function<T>::value, int> = 0>
void method1(T* p)
{
// ...
}
This might be considered over-engineering by some, but you could try the following:
Create an enum of each callback that you are interested in:
enum GlfwCallback {
KeyCallback,
FramebufferSizeCallback,
// etc.
};
Then create a type family that associates each of these with the corresponding function pointer type. Do this by creating a template struct and repeatedly specializing it:
template<GflwCallback callback>
struct GlfwCallbackType {};
template<>
struct GlfwCallbackType<KeyCallback> {
using CallbackType = GLFWkeyfun;
// or
using CallbackType = void(*)(GLFWwindow *, int, int, int, int);
};
template<>
struct GlfwCallbackType<FramebufferSizeCallback> {
using CallbackType = GLFWframebuffersizefun;
};
// etc.
Then you can write
template<GlfwCallback callback>
void method1(GlfwCallbackType<callback>::CallbackType p) {
// do something with p
method2<callback>(p);
};
Also, note that you can add other types and even static functions and data members to your "type family" as needed by your application.
A possibility to do what you want, but in a nice, type-safe fashion, would be the use of functors, i.e. classes that define an overloading for the operator().
Since a functor is a class, you could set the arguments as data memebers, and move the implementation/calling of the functions that you want to pass as arbitrary pointers into the operator() method, where you can have access to all the parameters through the this pointer.
Furthermore, you can define a hierarchy of functors, each one with specialized parameters and implementations, so you can modify the signature of method2 like the following:
method2(BaseFunctor* myfunctor) {
if (myfunctor)
(*myfucntor)();
}
and setup the right type of functor object in the calling context.
Also check out lambdas (c++11), that are basically a shortcut to functors definition.
I have a class B which derives from A:
template<class T>
class A
{
class iterator; // Defined fully
iterator begin ()
{
// Returns a pointer to the first element
}
iterator end ()
{
// Returns a pointer to the last element
}
}
template <class T>
class B : public A
{
// It automatically inherits the iterator
}
template <typename InputIterator>
void foo (InputIterator first,InputIterator last)
{
// Some code to infer whether it is of type A or B
}
Now some function say foo() is called using B::begin() at one time and sometime with A::begin().
I need to determine type during runtime to infer type and set some flag variables. How do I do this? I tried using typeinfo() but it returns the same value for both the iterators.
From library type_traits you can use some type magic:
is_base_of - returns true if Base is base of Derived.
is_same - returns true if A is the same type as B.
Everything with type_traits can be found here http://www.cplusplus.com/reference/type_traits/?kw=type_traits
They are not so runtime, it's only some magic with structs and templates, C++ does not support type as data by default. If you want so you can use Boost library, it does support types as I know.
UPD:
As comments under the question mentioned A::iterator is absolutely the same with B::iterator, so without looking at classes they are the same memory chunk.
So solution (maybe) is to create a little different function, what depends on classes actually:
template <typename LeftClass, typename RightClass>
void foo (LeftClass left, RightClass right)
{
if(is_same<LeftClass, RightClass>::value)
{
}
//Or that
if(is_same<LeftClass, A>::value && is_same<RightClass, A>::value)
}
Just don't forget to make this "friend" with classes.
typeinfo() returns the same value, because both A::begin() and B::begin() give you a value of the same type.
You should either have B::iterator inherit from A::iterator or have a special function in your iterator that returns a reference/pointer to it's container (which is then either of type A or type B).
I'm new to std::generate and have attempted to structure a program which uses it to initialize vectors. However it's behaving differently to my expectations.
I have an abstract base class:
template <typename G>
class RandomAllele {
public:
RandomAllele() { /* empty */ }
virtual ~RandomAllele() { /* empty */ }
virtual G operator()() const = 0;
};
Which is extended by (for example):
class RandomInt : public RandomAllele<int> {
public:
RandomInt(int max) : max_(max) {}
int operator()() const { return rand() % max_; }
private:
int max_;
};
I pass an instance of my inheriting class to a factory class by pointer, and then use it as the third argument for std::generate:
template<typename G, typename F>
class IndividualFactory {
public:
IndividualFactory(int length, const RandomAllele<G> *random_allele)
: length_(length), random_allele_(random_allele) { /* empty */ }
individual_type *generate_random() const {
std::vector<G> *chromosome = new std::vector<G>(length_);
std::generate(chromosome->begin(), chromosome->end(), *random_allele_); */
return new individual_type(chromosome);
}
private:
int length_;
RandomAllele<G> *random_allele_;
};
Now I get an error saying that RandomAllele cannot be instantiated because it's an abstract class. Why does generate need to instantiate it when the pointer already exists? And why is it trying to use the base class instead of the inheriting class RandomInt?
This works fine if I replace std::generate with:
for(auto iter = chromosome->begin(); iter != chromosome->end(); ++iter)
*iter = (*random_allele_)();
But I still wish to understand why it behaves strangely, and I'd prefer to use generate if there is a way to do this.
Thanks for your time,
Rhys
As others have mentioned above, the generate and generate_n functions take their generator objects by value, precluding you from directly using inheritance in this context.
However, one trick you can do is to apply the Fundamental Theorem of Software Engineering:
Any problem can be solved by adding another layer of indirection
Rather than directly passing in a polymorphic functor, instead pass in a wrapper functor that stores a pointer to this polymorphic functor and then forwards the call appropriately. For example:
template <typename T> class IndirectFunctor {
public:
explicit IndirectFunctor(RandomAllele<T>* f) : functor(f) {
// Handled in initializer list
}
T operator() () const {
return (*functor)();
}
private:
RandomAllele<T>* functor;
};
If you then pass this object into generate, as seen here:
RandomAllele<T>* functor = /* ... create an allele ... */
std::generate(begin, end, IndirectFunctor<T>(functor));
Then everything will work as intended. The reason for this is that if you copy IndirectFunctor<T> by value, then you just shallow-copy the stored pointer, which will still point to the RandomAllele you want to call. This avoids the slicing problem you were encountering because it never tries directly copying an object of type RandomAllele through a base class pointer. It always copies the wrapper object, which never tries to duplicate RandomAllele.
Hope this helps!
std::generate's generator is passed by value, and therefore copied.
In general the C++ standard library implements static polymorphism (templates) and doesn't support runtime polymorphism (virtual methods) for function objects. This is because it passes all its function objects by values, assuming them to be stateless or almost stateless such that the added indirection of passing by pointer or reference would be more expensive than by value.
Since it's passed by value this results in slicing and when you try to use a RandomAllele<G> it thinks you mean that exact class not whatever derived type it actually points to. Instead of templating on G just template on the exact generator functor type you desired directly.
The issue is that all standard algorithms take their arguments by value, to conform with traditional C constraints. So here the std::generate() algorithm take the functor by value. Your functor, of type RandomAllele<int>, is of abstract type. Yes, it's a pointer pointing at a concrete type, but the pointer is of an abstract type. In copying this object, the algorithm calls the copy constructor of RandomAllele<int>; i.e., the algorithm constructs an instance of abstract type. And this is something the C++ language forbids.
You can tell the runtime environment not to worry too much like so:
RandomInt *cp = dynamic_cast<RandomInt*>(random_allele);
if( ! cp ) {
// i thought the pointer is of RandomInt. It isn't. Err.
std::terminate(); // or something
}
std::generate(chromosome->begin(), chromosome->end(), *cp);
The prototype is:
template <class ForwardIterator, class Generator>
void generate ( ForwardIterator first, ForwardIterator last, Generator gen );
Hence gen is passed by value, so the compiler attempts to construct a RandomAllele by copy, hence problem.
The solution is to use an Envelope to provide the needed indirection:
template<class G>
class RandomAlleleEnvelope
{
public:
RandomAlleleEnvelope(const RandomAllele<G>* ra)
: ra_(ra)
{}
int operator()() const { return (*ra_)(); }
private:
const RandomAllele<G>* ra_;
};
std::generate<std::vector<int>::iterator,RandomAlleleEnvelope<int> >(chromosome->begin(), chromosome->end(), random_allele_);
Also note there is another solution, define your own generate to use a reference:
template <class ForwardIterator, class Generator>
void referenceGenerate ( ForwardIterator first, ForwardIterator last,
const Generator& gen )
{
while (first != last) *first++ = gen();
}
referenceGenerate(chromosome->begin(), chromosome->end(), *random_allele_);
I also think the following should work, that is to use the standard generate and explicitly make it handle a reference type:
std::generate<std::vector<int>::iterator, const RandomAllele<int>& >
(chromosome->begin(), chromosome->end(), *random_allele_);
I say should because this fails is instantiate on VS2010. On the other hand, if I can define my own:
template <class ForwardIterator, class Generator>
void myGenerate ( ForwardIterator first, ForwardIterator last, Generator gen )
{
while (first != last) *first++ = gen();
}
myGenerate<std::vector<int>::iterator, const RandomAllele<int>& >
(chromosome->begin(), chromosome->end(), *random_allele_);
The VS2010 fails because it implements std::generate is terms of another std::generate which defaults back to non-reference parameters.
I have a std::vector<T> of some type that's part of a class and that I need to iterate through in a lot of different places in my code, so I thought I'd be smart and create a function IterateAttributes, and pass it a boost::function object that I can in the loop and pass a single element and then I can pass any function to do work on the elements.
This seems a good idea until you have to implement it, then the problem comes of what does the passed in function return and does it need other arguments. It seems like I either have to find a way to do this more generically, like using templates, or I have to create overloads with function objects taking different args.
I think the first (more generic) options is probably better, however how would I go about that?
Below is a trial that doesn't work, however if I wanted to have a number of args, and all but the Attribute (a struct) arg mandatory. How should I go about it?
template <typename T> template <typename arg>
void ElementNode::IterateAttributes(boost::function<T (arg, Attribute)> func_)
{
std::vector<Attribute>::iterator it = v_attributes.begin();
for (; it != v_attributes.end(); it++)
{
func_(arg, *it);
}
}
Is that what you mean:
template <typename T, typename arg>
void ElementNode::IterateAttributes(boost::function<T (arg, Attribute)> func_, arg a)
{
std::vector<Attribute>::iterator it = v_attributes.begin();
for (; it != v_attributes.end(); it++)
{
func_(a, *it);
}
}
that allows only one parameter of any type - if you want you can introduce also version for more parameters.
About return value - what to do about it depends on what value it acctually is - the generic (and probably unnecesary) solution would be to return std::list<T>, but that would create more problems than it would solve i guess. If return type varies (not only in type but also in meaning) then I suggest modyfying templated function so it takes reference/pointer to overall result and updates it accordingly:
template <typename T> template <typename arg>
void ElementNode::IterateAttributes(boost::function<voidT (arg, Attribute, T&)> func_)
{
std::vector<Attribute>::iterator it = v_attributes.begin();
T result;
for (; it != v_attributes.end(); it++)
{
func_(arg, *it, result);
}
return result;
}
That's a quick workaround, it works but it's ugly, error prone, and pain to debug.
If you want variable parameter amount, then you would have to create several templates of above function - i just tested if it's possible:
template <typename T>
T boo(T){
}
template <typename T, typename TT>
TT boo(T,TT){
}
void test()
{
int i;
i= boo<int>(0);
i=boo<int,double>(0,0.0);
}
You must remember that functions passed to IterateAttributes must match exatly parameters given to Iterate function. That also means that you cannot use in it's prototype default values - probably you will have to define several overloaded versions like
void func_(Attribute,arg1, arg2,arg3){...}
void func_(Attribute A,arg1 a1,arg2 a2){func_(A,a1, a2,default3);}
void func_(Attribute A,arg1 a1){func_(A,a1, default2,default3);}
void func_(Attribute A){func_(A,default1, default2,default3);}
a) You want to iterate over the array and do something with each element there: in this case, you want functions that all take an array element and return void. Simple.
b) You want to partially apply functions with more arguments on each element: Write a custom functor around your function which stores the additional, pre-assigned arguments, or use boost::bind to effectively do the same.
Example:
vector<string> myStrings; // assign some values
// define a function with an additional argument
void myFunc(string message, string value)
{
cout << message << value << endl;
}
// allow partial application, i.e. "currying"
struct local_function
{
static string message;
static void myFunc_Curried(string value)
{
myFunc(message, value);
}
};
local_function::message = "the array contains: ";
// apply the curried function on all elements in the array
for_each(myStrings.begin(), myStrings.end(), local_function::myFunc_Curried);
The functor operates statically only for demonstration purposes. If message is bound to an instance of the struct, you will need something like boost::bind anyway to bind the instance pointer this in order to actually call the curried function. However, if the function I want to apply is used only locally, I prefer following the more readable static approach.
What you are trying to accomplish makes very good sense, and is also built directly into functional languages (for example F#). It is possible to achieve in C++, but requires some workarounds in the aforementioned case b. Please note if writing your own functor, as in my example, that it is common to place the arguments you want to curry away always at the beginning, and to "fill in" the arguments from the beginning to the end when partially applying.
Summarizing the comments and more thoughts:
Use bind to bind the other arguments, then use for_each on the resulting functor.
To handle return values, you need to think about what the return values mean. If you need to use the values in some way (say, perform a reduction, or use them to influence whether or not to continue performing the operation, etc), then you can use another functor to wrap the original to perform the thing you want.
You could do the same or more using BOOST_FOREACH or C++0x for each. That would even take less code to write.