I have a member function with two arguments. Both are pointers to complex objects. When called, the function performs some non-trivial computation and then returns an integer. Like this:
struct Fooer {
int foo(const A* a, const B* b);
};
The returned integer is always the same if foo() is given the same two arguments. This function is pretty heavily used, so it would make sense to memoize its result. Normally, some lookup table with the key being the pair of pointers would suffice. However, I'm in the unique position where I know all the call sites and I know that any given call site will always use the same pair of parameters during execution. This could greatly speed up memoization if only I could pass in a third parameter, a unique integer that is basically the cache hint:
struct Fooer {
int foo(const A* a, const B* b, int pos) {
if (cached_[pos] > 0) return cached_[pos];
cached_[pos] = /* Heavy computation. */ + 1;
return cached_[pos];
}
std::vector<int> cached_;
};
What I'm looking for is a mechanism to easily generate this 'cache hint'. But nothing comes to mind. For now, I'm manually adding this parameter to the call sites of foo(), but it's obviously ugly and fragile. The function is really heavily used so it's worth this kind of optimization, in case you're wondering.
More generally, I'd like to have some kind of 'thunk' at each call site that performs the heavy lifting the first time is called, then just returns the pre-computed integer.
Note that foo() is a member function so that different instances of Fooer should have different caches.
Would this approach help you?
struct Fooer {
using CacheMap = std::map<std::pair<const A*, const B*>, int>;
std::map<int, CacheMap> lineCache;
int foo(const A* a, const B* b, int line) {
const auto key = std::make_pair(a,b);
if (linecache.count(line) > 0) {
CacheMap& cacheMap = lineCache[line];
if(cacheMap.count(key)) return cacheMap[key];
}
lineCache[line][key] = /* Heavy computation. */ + 1;
return cacheMap[key];
}
};
// Calling
foo(a, b, __LINE__)
See _ReturnAddress or any alternatives for yours compiler. Maybe you can use it in your project. Obviously, if it work for you, than just create map caller-result.
Related
Please consider the following:
typedef int (*callback_function)(int a, int b);
class receiving_callbacks_class
{
public:
static register_callback(int iterator, callback_function fn)
{
function_list[iterator] = fn;
}
private:
static callback_function function_list[10];
}
This function_list is used by a C library, so it can do call backs on certain events.
I now would like to add a routine to every callback that gets registered via this function. So that it gets called like this:
default_routine();
fn();
I tried doing it with templates, but I could not find a way to do that inside the register_callback function. Every way to do it with templates meant wrapping the function to register before calling register_callback. I would like to contain this inside this particular class.
This differs from How to add standard routine to every function in array of function pointers? by adding the requirement that no changes can be made where register_callback is called; all changes must be within receiving_callbacks_class.
This is for an embedded system where I don't have the freedom to use std. All functions passed to the register_class function will be static.
Is this possible?
First, I would like to add a preamble explaining why this is difficult in general. There is a problem involving the amount of information being stored in the C library. Other C callbacks systems store two pieces of information per callback: the address of the function to call and arbitrary data cast to void*. The function is required to accept a void* argument in addition to the arguments required by the nature of the callback. This "extra" argument receives the arbitrary data. Casting this back to its original type allows access to as much extra data as needed; it could be null if no extra data is needed. (In this case, it would be cast back to callback_function.)
In the current context, however, the only information stored in the C library is the address of a function to call. This information must be different if different callbacks are to be invoked, hence there must be different functions. The requirement that the call site not be changed means that the different functions need to be provided by receiving_callbacks_class, yet these functions need to adapt when new callbacks are written by users of receiving_callbacks_class.
I can think of four main techniques for generating multiple similar functions in C++, but one of them uses macros, so let's call it three: lambdas, templates, and copy-paste. A lambda that captures the address of the real callback is no longer convertible to a function pointer, so no longer usable with the C library. A template would use the address of the real callback as the template parameter, which means that address would have to be a compile-time constant. However, C++ does not provide a way to require that a function argument be a compile-time constant, making the approach unsuitable for use inside register_callback(). That leaves copy-paste, which normally is a pain, but might be acceptable when the number of callbacks is as small as 10.
I can base an approach on the definition of function_list. There is a smallish limit on the number of callbacks passed to the C library and they can be invoked in constant time, given their index. This approach might be less appealing if the array is replaced by a container that does not support indexed access. It definitely becomes less appealing as the size of the container increases. It might be unusable if there is not a compile-time limit on the size of the container.
To receiving_callbacks_class I might add two pieces of static data: a second array of function pointers, and a size for both of the arrays.
class receiving_callbacks_class
{
public:
// Always use a symbolic constant when a magic number is needed more than once.
static constexpr unsigned MAX_CALLBACKS = 10;
// Looks the same (but with a return type), and called the same as before.
static void register_callback(int iterator, callback_function fn)
{
function_list[iterator] = fn;
}
private:
// Old array using the new symbolic constant
static callback_function function_list[MAX_CALLBACKS];
// A new array, probably should be `const`.
static const callback_function wrapper_list[MAX_CALLBACKS];
};
The new array is for storing pointers to wrapper functions, functions that will call default_routine() followed by the real callback. This array, not the old one, is what should be given to the C library. It still needs to be initialized, though. The initialization of the new array is where copy-paste comes in. I leave it to the reader to decide how large they would let MAX_CALLBACKS get before this is considered unmanageable. Personally, I found the copy-paste to be reasonable when the size is 10.
// Initialize the new array
const callback_function receiving_callbacks_class::wrapper_list[MAX_CALLBACKS] = {
[](int a, int b) -> int { default_routine(); return function_list[0](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[1](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[2](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[3](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[4](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[5](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[6](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[7](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[8](a, b); },
[](int a, int b) -> int { default_routine(); return function_list[9](a, b); },
};
It might be appropriate to add a null check on the appropriate function_list entry; I do not know how you handle having fewer than 10 callbacks.
Note that these lambdas are non-capturing, so they do convert to function pointers. They can be non-capturing only because their number is fixed at compile-time.
The last piece to change is what I mentioned before. The call into the C library would use the new array instead of the old. This was not included in the sample code, so I'll devise a name and parameter list.
//c_library(function_list, 10); // <-- replace this
c_library(wrapper_list, MAX_CALLBACKS); // <-- with this
Not my preferred setup, but it does meet the restrictions in the question.
I have two functions with the same name but different return types. I want to run the function based on their third parameter. If the third parameter is true I want to run the first and If the parameter is false to run the second function. I was trying different things on my own because I couldn't find information online and I wasn't sure how is this called. Here is what I tried to do:
static int function(int a, int b, const bool=true);
static std::string function(int a, int b, const bool=false);
I would be grateful if someone can explain how to do this or at least give me a link to some information.
This solution is not about having two different functions but if you wanted the function to return a different type depending on the bool value using boost::any.
boost::any function(int a, int b, const bool c) {
std::string str = "Hello world!";
int num = 10;
if ( c ) {
return boost::any(num);
} else {
return boost::any(str);
}
}
This would use the third parameter in the function in order to decide which return you should do. Depending on how big function is this might be a worse solution but if you really wanted to use a boolean as a parameter I believe this should work.
Docs: Boost
Related question to this answer: Function which returns an unknown type
You can create a function template and add specializations for the different return types. Then you could use the bool argument as a template parameter:
template<bool>
auto function(int, int);
template<>
auto function<true>(int a, int b)
{
// ...
return int{};
}
template<>
auto function<false>(int a, int b)
{
// ...
return std::string{};
}
The functions would then be called like this:
int a = function<true>(1,2);
std::string b = function<false>(1,2);
Here's a demo.
Note the important caveat that the bool parameter must be known at compile time, and can't be a run time argument.
While this technique will work, do be aware that this will confuse a lot of c++ programmers. They usually expect a function to always return a particular type.
More relevant to your question; this is not actually going to make the code much more readable. Instead, having separate named functions is probably a more readable approach:
int int_function(int a, int b);
std::string str_function(int a, int b);
which could be called like this:
int a = int_function(1,2);
std::string b = str_function(1,2);
In a function that takes several arguments of the same type, how can we guarantee that the caller doesn't mess up the ordering?
For example
void allocate_things(int num_buffers, int pages_per_buffer, int default_value ...
and later
// uhmm.. lets see which was which uhh..
allocate_things(40,22,80,...
A typical solution is to put the parameters in a structure, with named fields.
AllocateParams p;
p.num_buffers = 1;
p.pages_per_buffer = 10;
p.default_value = 93;
allocate_things(p);
You don't have to use fields, of course. You can use member functions or whatever you like.
If you have a C++11 compiler, you could use user-defined literals in combination with user-defined types. Here is a naive approach:
struct num_buffers_t {
constexpr num_buffers_t(int n) : n(n) {} // constexpr constructor requires C++14
int n;
};
struct pages_per_buffer_t {
constexpr pages_per_buffer_t(int n) : n(n) {}
int n;
};
constexpr num_buffers_t operator"" _buffers(unsigned long long int n) {
return num_buffers_t(n);
}
constexpr pages_per_buffer_t operator"" _pages_per_buffer(unsigned long long int n) {
return pages_per_buffer_t(n);
}
void allocate_things(num_buffers_t num_buffers, pages_per_buffer_t pages_per_buffer) {
// do stuff...
}
template <typename S, typename T>
void allocate_things(S, T) = delete; // forbid calling with other types, eg. integer literals
int main() {
// now we see which is which ...
allocate_things(40_buffers, 22_pages_per_buffer);
// the following does not compile (see the 'deleted' function):
// allocate_things(40, 22);
// allocate_things(40, 22_pages_per_buffer);
// allocate_things(22_pages_per_buffer, 40_buffers);
}
Two good answers so far, one more: another approach would be to try leverage the type system wherever possible, and to create strong typedefs. For instance, using boost strong typedef (http://www.boost.org/doc/libs/1_61_0/libs/serialization/doc/strong_typedef.html).
BOOST_STRONG_TYPEDEF(int , num_buffers);
BOOST_STRONG_TYPEDEF(int , num_pages);
void func(num_buffers b, num_pages p);
Calling func with arguments in the wrong order would now be a compile error.
A couple of notes on this. First, boost's strong typedef is rather dated in its approach; you can do much nicer things with variadic CRTP and avoid macros completely. Second, obviously this introduces some overhead as you often have to explicitly convert. So generally you don't want to overuse it. It's really nice for things that come up over and over again in your library. Not so good for things that come up as a one off. So for instance, if you are writing a GPS library, you should have a strong double typedef for distances in metres, a strong int64 typedef for time past epoch in nanoseconds, and so on.
(Note: post was originally tagged 'C`)
C99 onwards allows an extension to #Dietrich Epp idea: compound literal
struct things {
int num_buffers;
int pages_per_buffer;
int default_value
};
allocate_things(struct things);
// Use a compound literal
allocate_things((struct things){.default_value=80, .num_buffers=40, .pages_per_buffer=22});
Could even pass the address of the structure.
allocate_things(struct things *);
// Use a compound literal
allocate_things(&((struct things){.default_value=80,.num_buffers=40,.pages_per_buffer=22}));
You can't. That's why it is recommended to have as few function arguments as possible.
In your example you could have separate functions like set_num_buffers(int num_buffers), set_pages_per_buffer(int pages_per_buffer) etc.
You probably have noticed yourself that allocate_things is not a good name because it doesn't express what the function is actually doing. Especially I would not expect it to set a default value.
Just for completeness, you could use named arguments, when your call becomes.
void allocate_things(num_buffers=20, pages_per_buffer=40, default_value=20);
// or equivalently
void allocate_things(pages_per_buffer=40, default_value=20, num_buffers=20);
However, with the current C++ this requires quite a bit of code to be implemented (in the header file declaring allocate_things(), which must also declare appropriate external objects num_buffers etc providing operator= which return a unique suitable object).
---------- working example (for sergej)
#include <iostream>
struct a_t { int x=0; a_t(int i): x(i){} };
struct b_t { int x=0; b_t(int i): x(i){} };
struct c_t { int x=0; c_t(int i): x(i){} };
// implement using all possible permutations of the arguments.
// for many more argumentes better use a varidadic template.
void func(a_t a, b_t b, c_t c)
{ std::cout<<"a="<<a.x<<" b="<<b.x<<" c="<<c.x<<std::endl; }
inline void func(b_t b, c_t c, a_t a) { func(a,b,c); }
inline void func(c_t c, a_t a, b_t b) { func(a,b,c); }
inline void func(a_t a, c_t c, b_t b) { func(a,b,c); }
inline void func(c_t c, b_t b, a_t a) { func(a,b,c); }
inline void func(b_t b, a_t a, c_t c) { func(a,b,c); }
struct make_a { a_t operator=(int i) { return {i}; } } a;
struct make_b { b_t operator=(int i) { return {i}; } } b;
struct make_c { c_t operator=(int i) { return {i}; } } c;
int main()
{
func(b=2, c=10, a=42);
}
Are you really going to try to QA all the combinations of arbitrary integers? And throw in all the checks for negative/zero values etc?
Just create two enum types for minimum, medium and maximum number of buffers, and small medium and large buffer sizes. Then let the compiler do the work and let your QA folks take an afternoon off:
allocate_things(MINIMUM_BUFFER_CONFIGURATION, LARGE_BUFFER_SIZE, 42);
Then you only have to test a limited number of combinations and you'll have 100% coverage. The people working on your code 5 years from now will only need to know what they want to achieve and not have to guess the numbers they might need or which values have actually been tested in the field.
It does make the code slightly harder to extend, but it sounds like the parameters are for low-level performance tuning, so twiddling the values should not be perceived as cheap/trivial/not needing thorough testing. A code review of a change from
allocate_something(25, 25, 25);
...to
allocate_something(30, 80, 42);
...will likely get just a shrug/blown off, but a code review of a new enum value EXTRA_LARGE_BUFFERS will likely trigger all the right discussions about memory use, documentation, performance testing etc.
I'm doing a linear genetic programming project, where programs are bred and evolved by means of natural evolution mechanisms. Their "DNA" is basically a container (I've used arrays and vectors successfully) which contain function pointers to a set of functions available.
Now, for simple problems, such as mathematical problems, I could use one type-defined function pointer which could point to functions that all return a double and all take as parameters two doubles.
Unfortunately this is not very practical. I need to be able to have a container which can have different sorts of function pointers, say a function pointer to a function which takes no arguments, or a function which takes one argument, or a function which returns something, etc (you get the idea)...
Is there any way to do this using any kind of container ?
Could I do that using a container which contains polymorphic classes, which in their turn have various kinds of function pointers?
I hope someone can direct me towards a solution because redesigning everything I've done so far is going to be painful.
A typical idea for virtual machines is to have a separate stack that is used for argument and return value passing.
Your functions can still all be of type void fn(void), but you do argument passing and returning manually.
You can do something like this:
class ArgumentStack {
public:
void push(double ret_val) { m_stack.push_back(ret_val); }
double pop() {
double arg = m_stack.back();
m_stack.pop_back();
return arg;
}
private:
std::vector<double> m_stack;
};
ArgumentStack stack;
...so a function could look like this:
// Multiplies two doubles on top of the stack.
void multiply() {
// Read arguments.
double a1 = stack.pop();
double a2 = stack.pop();
// Multiply!
double result = a1 * a2;
// Return the result by putting it on the stack.
stack.push(result);
}
This can be used in this way:
// Calculate 4 * 2.
stack.push(4);
stack.push(2);
multiply();
printf("2 * 4 = %f\n", stack.pop());
Do you follow?
You cannot put a polymorphic function in a class, since functions that take (or return) different things cannot be used in the same way (with the same interface), which is something required by polymorphism.
The idea of having a class providing a virtual function for any possible function type you need would work, but (without knowing anything about your problem!) its usage feels weird to me: what functions would a derived class override? Aren't your functions uncorrelated?
If your functions are uncorrelated (if there's no reason why you should group them as members of the same class, or if they would be static function since they don't need member variables) you should opt for something else... If you pick your functions at random you could just have several different containers, one for function type, and just pick a container at random, and then a function within it.
Could you make some examples of what your functions do?
What you mentioned itself can be implemented probably by a container of
std::function or discriminated union like Boost::variant.
For example:
#include <functional>
#include <cstdio>
#include <iostream>
struct F {
virtual ~F() {}
};
template< class Return, class Param = void >
struct Func : F {
std::function< Return( Param ) > f;
Func( std::function< Return( Param ) > const& f ) : f( f ) {}
Return operator()( Param const& x ) const { return f( x ); }
};
template< class Return >
struct Func< Return, void > : F {
std::function< Return() > f;
Func( std::function< Return() > const& f ) : f( f ) {}
Return operator()() const { return f(); }
};
static void f_void_void( void ) { puts("void"); }
static int f_int_int( int x ) { return x; }
int main()
{
F *f[] = {
new Func< void >( f_void_void ),
new Func< int, int >( f_int_int ),
};
for ( F **a = f, **e = f + 2; a != e; ++ a ) {
if ( auto p = dynamic_cast< Func< void >* >( *a ) ) {
(*p)();
}
else if ( auto p = dynamic_cast< Func< int, int >* >( *a ) ) {
std::cout<< (*p)( 1 ) <<'\n';
}
}
}
But I'm not sure this is really what you want...
What do you think about Alf P. Steinbach's comment?
This sort of thing is possible with a bit of work. First it's important to understand why something simpler is not possible: in C/C++, the exact mechanism by which arguments are passed to functions and how return values are obtained from the function depends on the types (and sizes) of the arguments. This is defined in the application binary interface (ABI) which is a set of conventions that allow C++ code compiled by different compilers to interoperate. The language also specifies a bunch of implicit type conversions that occur at the call site. So the short and simple answer is that in C/C++ the compiler cannot emit machine code for a call to a function whose signature is not known at compile time.
Now, you can of course implement something like Javascript or Python in C++, where all values (relevant to these functions) are typed dynamically. You can have a base "Value" class that can be an integer, float, string, tuples, lists, maps, etc. You could use std::variant, but in my opinion this is actually syntactically cumbersome and you're better of doing it yourself:
enum class Type {integer, real, str, tuple, map};
struct Value
{
// Returns the type of this value.
virtual Type type() const = 0;
// Put any generic interfaces you want to have across all Value types here.
};
struct Integer: Value
{
int value;
Type type() const override { return Type::integer; }
};
struct String: Value
{
std::string value;
Type type() const override { return Type::str; }
};
struct Tuple: Value
{
std::vector<Value*> value;
Type type() const override { return Type::tuple; };
}
// etc. for whatever types are interesting to you.
Now you can define a function as anything that takes a single Value* and returns a single Value*. Multiple input or output arguments can be passed in as a Tuple, or a Map:
using Function = Value* (*)(Value*);
All your function implementations will need to get the type and do something appropriate with the argument:
Value* increment(Value* x)
{
switch (x->type())
{
Type::integer:
return new Integer(((Integer*) x)->value + 1);
Type::real:
return new Real(((Real*) x)->value + 1.0);
default:
throw TypeError("expected an integer or real argument.")
}
}
increment is now compatible with the Function type and can be stored in mFuncs. You can now call a function of unknown type on arguments of unknown type and you will get an exception if the arguments don't match, or a result of some unknown type if the arguments are compatible.
Most probably you will want to store the function signature as something you can introspect, i.e. dynamically figure out the number and type of arguments that a Function takes. In this case you can make a base Function class with the necessary introspection functions and provide it an operator () to make it look something like calling a regular function. Then you would derive and implement Function as needed.
This is a sketch, but hopefully contains enough pointers to show the way. There are also more type-safe ways to write this code (I like C-style casts when I've already checked the type, but some people might insist you should use dynamic_cast instead), but I figured that is not the point of this question. You will also have to figure out how Value* objects lifetime is managed and that is an entirely different discussion.
Suppose you have a function, and you call it a lot of times, every time the function return a big object. I've optimized the problem using a functor that return void, and store the returning value in a public member:
#include <vector>
const int N = 100;
std::vector<double> fun(const std::vector<double> & v, const int n)
{
std::vector<double> output = v;
output[n] *= output[n];
return output;
}
class F
{
public:
F() : output(N) {};
std::vector<double> output;
void operator()(const std::vector<double> & v, const int n)
{
output = v;
output[n] *= n;
}
};
int main()
{
std::vector<double> start(N,10.);
std::vector<double> end(N);
double a;
// first solution
for (unsigned long int i = 0; i != 10000000; ++i)
a = fun(start, 2)[3];
// second solution
F f;
for (unsigned long int i = 0; i != 10000000; ++i)
{
f(start, 2);
a = f.output[3];
}
}
Yes, I can use inline or optimize in an other way this problem, but here I want to stress on this problem: with the functor I declare and construct the output variable output only one time, using the function I do that every time it is called. The second solution is two time faster than the first with g++ -O1 or g++ -O2. What do you think about it, is it an ugly optimization?
Edit:
to clarify my aim. I have to evaluate the function >10M times, but I need the output only few random times. It's important that the input is not changed, in fact I declared it as a const reference. In this example the input is always the same, but in real world the input change and it is function of the previous output of the function.
More common scenario is to create object with reserved large enough size outside the function and pass large object to the function by pointer or by reference. You could reuse this object on several calls to your function. Thus you could reduce continual memory allocation.
In both cases you are allocating new vector many many times.
What you should do is to pass both input and output objects to your class/function:
void fun(const std::vector<double> & in, const int n, std::vector<double> & out)
{
out[n] *= in[n];
}
this way you separate your logic from the algorithm. You'll have to create a new std::vector once and pass it to the function as many time as you want. Notice that there's unnecessary no copy/allocation made.
p.s. it's been awhile since I did c++. It may not compile right away.
It's not an ugly optimization. It's actually a fairly decent one.
I would, however, hide output and make an operator[] member to access its members. Why? Because you just might be able to perform a lazy evaluation optimization by moving all the math to that function, thus only doing that math when the client requests that value. Until the user asks for it, why do it if you don't need to?
Edit:
Just checked the standard. Behavior of the assignment operator is based on insert(). Notes for that function state that an allocation occurs if new size exceeds current capacity. Of course this does not seem to explicitly disallow an implementation from reallocating even if otherwise...I'm pretty sure you'll find none that do and I'm sure the standard says something about it somewhere else. Thus you've improved speed by removing allocation calls.
You should still hide the internal vector. You'll have more chance to change implementation if you use encapsulation. You could also return a reference (maybe const) to the vector from the function and retain the original syntax.
I played with this a bit, and came up with the code below. I keep thinking there's a better way to do this, but it's escaping me for now.
The key differences:
I'm allergic to public member variables, so I made output private, and put getters around it.
Having the operator return void isn't necessary for the optimization, so I have it return the value as a const reference so we can preserve return value semantics.
I took a stab at generalizing the approach into a templated base class, so you can then define derived classes for a particular return type, and not re-define the plumbing. This assumes the object you want to create takes a one-arg constructor, and the function you want to call takes in one additional argument. I think you'd have to define other templates if this varies.
Enjoy...
#include <vector>
template<typename T, typename ConstructArg, typename FuncArg>
class ReturnT
{
public:
ReturnT(ConstructArg arg): output(arg){}
virtual ~ReturnT() {}
const T& operator()(const T& in, FuncArg arg)
{
output = in;
this->doOp(arg);
return this->getOutput();
}
const T& getOutput() const {return output;}
protected:
T& getOutput() {return output;}
private:
virtual void doOp(FuncArg arg) = 0;
T output;
};
class F : public ReturnT<std::vector<double>, std::size_t, const int>
{
public:
F(std::size_t size) : ReturnT<std::vector<double>, std::size_t, const int>(size) {}
private:
virtual void doOp(const int n)
{
this->getOutput()[n] *= n;
}
};
int main()
{
const int N = 100;
std::vector<double> start(N,10.);
double a;
// second solution
F f(N);
for (unsigned long int i = 0; i != 10000000; ++i)
{
a = f(start, 2)[3];
}
}
It seems quite strange(I mean the need for optimization at all) - I think that a decent compiler should perform return value optimization in such cases. Maybe all you need is to enable it.