Perhaps I am way out of left field with this question, but is it possible to define a member function via the constructor?
In my case, I am trying to write a class to perform robust model fitting (using RANSAC). I want this to be generalizable to different types of models. For example, I could use this to determine an estimate of a plane to a set of 3D points. Or, perhaps I could determine a transformation between two sets of points. In these two examples, there might need to be different error functions and different fitting functions. Instead of using a class, a static function call might look like
model = estimate(data, &fittingFunc, &errorFunc);
I'm wondering if I can have member instance for those modular functions?
Something like
class Estimator
{
private:
// estimation params
double errorFunc(std::vector<dtype>, double threshold); // Leave this unimplemented
double fittingFunc(std::vector<dtype>, Parameters p); // Leave this unimplemented
public:
Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double));
dtype estimate(data); // Estimates model of type dtype. Gets implemented
};
Estimator::Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
{
fittingFunc = fittingFunc;
errorFunc = errorFunc;
}
I imagine I have bastardized the proper syntax in my example, but I hope the question is clear. Basically I am asking: Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?
Secondly, even if this is possible, is it considered bad form?
UPDATE: If it helps, here is MATLAB code for robust estimation that has this sort of generalizable structure I'm hoping to replicate in C++
Can the constructor accept function pointers as arguments and assign them to be the implementation of member functions?
No. Not as member functions. But you can certainly have public member function pointers:
class Estimator
{
public:
double (*errorFunc)(std::vector<dtype>, double threshold);
double (*fittingFunc)(std::vector<dtype>, Parameters p);
public:
Estimator(void (*fittingFunc(std::vector<dtype>, Parameters), void (*errorFunc(std::vector<dtype>, double))
: errorFunc(errorFunc)
, fittingFunc(fittingFunc)
{ }
dtype estimate(data);
};
For a nicer (or safer) interface, you can make the function pointers private and have a public member function which simply invokes them.
More generally, if you're okay with the overhead, you can have members of type std::function<double(std::vector<dtype>, double)> and std::function<double(std::vector<dtype>, Parameters)> and then you can use a wider variety of callables (function pointers, but also lambdas, bound member functions, etc.)
Yes you can provide the algorithm for your fitting and error function. You could do it using pointer to function. And there is a better solution, in the standard header you will find the template std::function which can be constructed with pointer to function but also with functors or lambda expressions.
Your class would be something like this:
#include <functional>
class Estimator
{
private:
// estimation params
using error_func_type = std::function<double(std::vector<dtype>,double)>;
using fitting_func_type = std::function<double(std::vector<dtype>,Parameters p)>;
fitting_func_type fittingFunc;
error_func_type errorFunc;
public:
Estimator(fitting_funct_type fit, error_funct_type err)
:fittingFunc(fit),errorFunc(err){}
dtype estimate(data); // Estimates model of type dtype. Gets implemented
};
Related
I've tried various solutions on SO to solve this problem, yet I must be doing something wrong.
I have several classes where methods in each of the classes have the same method signature:
typedef int (*ControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
And an example class having some method using that signature:
class StaticContentController {
public:
int handleStaticContentRequest(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms) {
return 1;
}
}
Now I try to create a map of pointers to member functions:
std::map<std::string, ControllerMethod> operations;
operations.emplace("staticContent", &StaticContentController::handleStaticContentRequest);
std::string d("test.txt");
ControllerMethod f = operations["staticContent"];
auto s = ((_staticContentController).*f)(d, pooledQueries); // <- compile error here
but calling the method gives the compile error
Right hand operand to .* has non-pointer-to-member type 'web::server::ControllerMethod'
What am I missing?
Update:
I now have an empty Controller base class which other controller classes inherit from:
namespace web { namespace server {
class Controller {
};
typedef ControllerResponse (Controller::*ControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
}}
Now I'm getting the following error at operations.emplace():
No matching constructor for initialization of 'std::__1::pair<const std::__1::basic_string<char>, web::server::ControllerResponse
Updated answer
You're trying to use two different paradigms here, and they aren't really compatible with one another. If I interpret your edit correctly, you're trying to create a map of functions that call into other classes, and you want to declare this map as a set of function pointers.
Function pointers are an assembly level construct, exposed by C. The syntax reflects this - and getting a C++ class to conform to this is not possible without help - namely, adding a context pointer parameter that is associated with every function pointer, and converting the context pointer to a class instance to call the member function.
So, how do we fix the problem?
In both of the next approaches, we need a context object associated with the function table. This involves creating a structure to hold the member function and the context:
template<typename T> struct FunctionTableEntry
{
ControllerMethod Function;
T* Context;
};
and our function pointer becomes the following:
typedef ControllerResponse (T::*ControllerMethod)(const std::string &data, const StringMap ¶ms);
Here, StringMap is a typedef for std::unordered_map<std::string, std::string>.
Our main problem now comes with removing the template parameter T, as we can't make maps of runtime defined templates (a template who's type will only be known at run time).
There are two main approaches to take in resolving this, and both have issues that will need to be considered. The first is to perform C style type erasure with pointers and very careful association. The second is to abandon function pointers in favor of C++ function objects.
C-Style Type Erasure
This option involves using C-style casts to convert the class instance pointer to its base class type, the member function pointer to the type expected by the function declaration, and then making the call as though the base class defines the method. This requires the use of pointers, and cannot be done without them.
To do this, our FunctionTableEntry structure changes to the following:
struct FunctionTableEntry
{
ControllerMethod Function;
Controller* Context;
}
and our function pointer to:
typedef ControllerResponse (Controller::*ControllerMethod)(const std::string &data, const StringMap ¶ms);
To add a new entry, we do the following:
std::map<std::string, FunctionTableEntry> operations;
FunctionTableEntry Entry;
Entry.Function = (ControllerMethod)&StaticContentController::handleStaticContentRequest;
Entry.Context = (Controller*)&_staticContentController;
operations.emplace("staticContent", Entry);
And to call it:
FunctionTableEntry f = operations["staticContent"];
auto s = ((f.Context)->*f.Function)(d, pooledQueries);
This method suffers from a few drawbacks - first, you have no other choice but to use pointers to refer to your controller objects - casting will not function properly otherwise. You can make this a bit more C++ friendly with std::shared_ptr, but otherwise, there is no way to replace it. This also means you need to carefully manage the lifetime of your controller objects. If they get freed while the function table is still referencing them you will almost certainly crash the system.
Second, the casting can cause issues with complex inheritance hierarchies. This method only works if (Controller*)_staticContentController == _staticContentController, i.e. casting to the base class gives the same numerical pointer value. Otherwise, the called method will fail as it will not be able to properly reference its local data.
This method has the advantage of being quite fast, however. There is no function overhead besides the table lookup, and the generated assembly is not much more than just calling the function normally. It is also runtime independent - so long as the equality expression above is true with all users of the controller system, anyone with a C++ compiler can create a new controller and this system will be able to call their functions, even if they use a completely different runtime library.
Additionally, if you know the controller instance is going to be used with multiple functions, you can modify the structure to provide a map of functions associated with one Context value, allowing you to reduce some of the memory overhead. This may not be possible with your design, but it's worth looking into if memory is a concern.
C++ Function Objects
The second solution is to completely do away with C-style function pointers altogether and use std::function. Since std::function can contain instance data as part of itself, and can be placed into a map, this allows you to std::bind a member function, creating a partially specified function call (I believe in functional programming this is what's called a closure).
In this case, there is no FunctionTableEntry structure - instead we use the following:
typedef std::function<ControllerResponse(const std::string&, const StringMap&)> ControllerMethod;
To add a new method, we do the following:
std::map<std::string, ControllerMethod> operations;
operations.emplace("staticContent", std::bind(&StaticContextController::handleStaticContentRequest, &_staticContentController, std::placeholders::_1, std::placeholders::_2);
This creates a closure that calls the member function with the required controller instance.
To call this, we do the following:
std::string d("test.txt");
ControllerMethod f = operations["staticContent"];
auto s = f(d, pooledQueries);
C++ function objects override operator (), which allows them to work as though they were static functions.
This method allows for both member functions and static functions to exist in the same map. It also allows for complex inheritance hierarchies to occur, as there is no casting to make things function - everything occurs with template functions.
The downside to this method is you still need to deal with object lifespan - the content controller objects cannot be destroyed until after the function map has been cleared. In addition, there is some overhead due to the use of std::function with placeholder parameters (though that likely depends on the runtime library in use, my tests have shown it generates a whole lot more code in x86-64 GCC 9.3).
This method also is not runtime independent - whatever runtime you choose to use here must also be used by every programmer that uses this code, otherwise incompatibilities in the way each library creates and stores std::function will cause strange failures. This means no compiler mixing - if you used MSVC 2019 to build the API, everyone else who uses this library must use MSVC2019 to build their controller component. If you aren't providing an API here, then this is not an issue.
Original answer
Your function pointer declaration is wrong - pointers to members have a different syntax to the normal function pointer typedef.
A normal function pointer uses the syntax you have currently:
typedef int (*foo)(int x, int y);
A pointer to member function typedef looks like this:
typedef int (SomeClass::*foo)(int x, int y);
The SomeClass:: section is required as pointers to members have an additional parameter to them, called this. In C++, the this pointer is passed as the first argument to the function, which makes the function declaration different (as the actual assembly code needed to call the function is different, see MSVC generated assembly for a real world example).
To solve the issue, you need to provide a base class that can be used to declare the typedef, then inherit from that class to allow the method to be called. This is effectively identical to using inheritance, unless you have multiple methods in the same type that have the same signature, but do different things.
The DirectX 11 Effects framework uses this exact paradigm to avoid branching when configuring different shader types in the graphics pipeline - see here, at line 590.
As pointed out, the type of a non-static member function of the class StaticContentController is not:
typedef int (*ControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
Instead, it is:
typedef int (StaticContentController::*StaticContentControllerMethod)(const std::string &data, const std::unordered_map<std::string, std::string> ¶ms);
This was your initial error.
This makes sense as you need an instance to call the member function, and the instance has a type as well. And it makes sense that if you have a Base::*Function pointer, you can call it with an instance of a class publicly and unambiguously derived from Base, because a derived pointer can be converted implicitly to a base pointer.
It also makes sense that you cannot assign a Derived::*Function pointer to a Base::*Function pointer because the result could be called with any Base instance, which need not be a Derived instance. This was the error in the question update.
In this very limited circumstance, C++ behaves completely logically.
With the modification to the correct type, your snippet will compile:
std::map<std::string, StaticContentControllerMethod> operations;
operations.emplace("staticContent",
&StaticContentController::handleStaticContentRequest);
std::string d("test.txt");
StaticContentControllerMethod f = operations["staticContent"];
auto s = ((_staticContentController).*f)(d, pooledQueries); // <- works
So presumably your actual question is how to store in this map member function pointers for multiple classes and not just StaticContentController. But that is the wrong question. You have to have the instance (_staticContentController) to invoke the member function pointer, so you already know the type.
So maybe you want to ask how to erase the type. One way is storing something that doesn't require an instance: for that, use std::function as the mapped type and bind the instance when inserting into the map. That would work and be straightforward if you have the controller at the time the map is created. A second way is using a type erasing type like std::any for the mapped type, and use any_cast at the point of use to return it to its initial type. A third way is to use a common base class with virtual functions which are overridden in your classes. Since the virtual functions can be called with a base pointer, you can store member function pointers of the base class.
Alternatively, maybe you want to ask how to have a type-indexed collection: the type is known at lookup time (because you have an instance) and you need to lookup a value whose type (member function pointer) depends on the "key" type.
The simplest way to do this is to have templated classes, and let the compiler handle the mapping:
template<typename T>
struct operations {
static std::map<std::string, void (T::*)(etc.)> pointers;
};
// use:
operations<StaticContentController>::pointers["staticContent"];
Another version of type-indexing might have the following interface:
template<template<typename> typename Value>
class type_keyed_map
{
public:
template<typename T>
void insert(std::unique_ptr<Value<T>> value);
template<typename T>
auto find() -> Value<T>*; // return null if not found
};
You can use a std::map in the implementation, but std::map does not allow multiple value types.
I am trying to use dlib to minimize a function where I can calculate the function and it's gradient at a given parameter value, using find_min.
As the function changes depending on input, I have defined a class with the inputs as members of the class, and two public functions which calculate the function and its gradient at the current guess of the solution:
#include <dlib/matrix.h>
typedef dlib::matrix<double,0,1> column_vector;
class Link
{
public:
// Initialisation
Link(const column_vector& predictors, const column_vector& responses)
: _predictors(predictors), _responses(responses)
{
}
// Likelihood and first derivative
double likelihood(const column_vector& b) const;
column_vector gradient(const column_vector& b) const;
protected:
column_vector _predictors;
column_vector _responses;
};
(omitting the code to calculate these functions for simplicity).
I then run through a loop of predictors and responses, minimising each case:
column_vector starting_point(2);
Link linear(x, y);
dlib::find_min(dlib::bfgs_search_strategy(),
dlib::objective_delta_stop_strategy(1e-7),
linear.likelihood,
linear.gradient,
starting_point);
However, I get a compiler error from trying to provide the non-static member functions linear.likelihood and linear.gradient from Link: 'reference to non-static member function must be called'.
I'd previously gotten this to work by overloading operator() when using only the likelihood, but can't do this with two functions (likelihood and gradient). Turning these into function pointers gives the same error.
Searching other answers I've found similar problems with trying to pass non-static member functions as arguments, but couldn't get them to work here. Is there a standard solution using template arguments I should be using to fix this?
Or am I going about this problem the wrong way entirely, and I shouldn't be using a class like this?
The arguments to dlib::find_min() have to be objects that can be called with the function-call operator(). linear.likelihood() calls the likelihood function and returns a result, but linear.likelihood by itself is not well-formed C++.
An easy solution is to use lambda expressions and to capture the object linear by reference. The lambda expression is a temporary object that is callable.
dlib::find_min(dlib::bfgs_search_strategy(),
dlib::objective_delta_stop_strategy(1e-7),
[&linear](const column_vector& a) {
return linear.likelihood(a);
},
[&linear](const column_vector& b) {
return linear.gradient(b);
},
starting_point);
I am working on a fairly tightly coupled library which up until now has explicitly assumed all computations are done with doubles. I'm in the process of converting some of the core classes to templates so that we can start computing with std::complex<double>. I've templated about 10 of our classes so far have noticed a tendency toward proliferation of templates. As one class becomes templated, any other class that uses the templated class appears to need templating as well. I think I can avoid some of this proliferation by defining abstract base classes for my templates so that other classes can just use pointers to the abstract class and then refer to either a double or std::complex<double> version of the derived class. This seems to work on at the header level, but when I dive into the source files, the templated class will often have functions which compute a value or container of values of type double or std::complex<double>. It seems like a waste to template a whole class just because a couple of lines in the source file are different because of some other classes return type.
The use of auto seems like a possible way to fix this, but I'm not 100% sure it would work. Suppose I have an abstract base class AbstractFunction from which Function<Scalar> derives, where Scalar can be double or std::complex<double>. Now suppose we have two member functions:
virtual Scalar Function<Scalar>::value(double x);
virtual void Function<Scalar>::values(std::vector<Scalar> &values, std::vector<double> x);
And suppose I have some other class (that I don't want to template) with a member function that calls one of these.
// populate double x and std::vector<double> xs
auto value = functionPtr->value(x);
std::vector<auto> values;
functionPtr->values(values, xs);
// do something with value and values
where functionPtr is of type std::shared_ptr<AbstractFunction>.
I could see auto working for the first case, but I don't believe I could construct a vector of auto to be filled with the second one. Does this necessitate making the calling class a template? Can someone recommend another strategy to cut down on the proliferation of templates?
I think you are already wrong in assuming that the first use-case is going to work. If you have an abstract base class, then either value is a member of it and you can call it through std::shared_ptr<AbstractFunction> or value is not a member of it and only available if you know the derived class' type. In the first case, the AbstractFunction::value method must have a fixed return type, it can not depend on Scalar, which is the template parameter of the derived class.
That said: In my experience the two concept often don't mix well. You either want to create an abstract base class with the full interface or you want a template. In the latter case, there is often no need / no benefit for having an abstract base class. It then follows that also the code using your template works with templates.
What might help you is to "export" the template parameter from Function, i.e.
template<typename T>
class Function
{
public:
using value_type = T;
value_type value() const;
// ...
};
and in other parts of the code, use a template which takes any T which behaves like Function if you don't want to directly write out (and limit yourself) to Function:
template<typename T>
void something( const std::shared_ptr<T>& functionPtr )
{
// ignoring where x comes from...
using V = typename T::value_type;
V value = functionPtr->value(x);
std::vector<V> values;
functionPtr->values(values, xs);
}
Note that this is just one option, I don't know if it is the best option for your use-case.
I have seen code like this, so I'm trying to find the reason.
What's the main reason for having static functions that act as constructors, instead of having actual constructors?
I mean something like:
class MyClass
{
public:
static MyClass CreateFrom( bar );
static MyClass CreateFrom( foo );
...
}
instead of:
class MyClass
{
public:
MyClass( bar );
MyClass( foo );
...
}
This is called the "named constructor idiom".
It's typically used when:
You have a lot of ctors with similar enough enough parameter lists that overloaded ctors would be confusing (e.g., different mixtures of integer and floating point numbers, so 1, 1.0, 1 is supposed to mean something different from 1, 1, 1.0).
You have two different sources that both provide the input as the same type. For example, let's assume you wanted to convert a distance on the surface of the earth into the angle subtended between points that distance apart -- but you might want to supply the distance in either miles or kilometers, either of which would be represented as a double.
In this case a single angle(double dist) can't distinguish between input in kilometer vs. miles, but: angle_from_miles and angle_from_kilomters can do that quite easily.
They are called Named Constructors.
The are basically used when you want to construct an object which requires to pass a particular set of parameters but internally you need to construct the object differently.
For example you have a class like:
class AREA
{
double area;
AREA(int x);
};
//how will you construct the object differently in case of circle and square??
For this purpose, we have named constructors which help to create a relevant object.
So we may create 2 static methods inside the class as:
static AREA square(int x)
{ return AREA(x*x); }
and
static AREA circle(int x)
{ return AREA(x*x*3.14); } //or a more accurate PI value
Thus, we may call the relevant static function to return the object initialized with the required area.
NOTE: These are static as while creating an object for a particular class you shouldn't be requiring an object to do so.
Check THIS for more details.
The most obvious benefits are:
It's easy to specify the implementation which constructs the instance at the callsite, when multiple constructors are provided. This makes it easier for the class to provide multiple variants.
These variants may also have different names, but identical parameter lists (or parameter lists which the compiler may call out as ambiguous when determining which to choose).
It helps you because you can read which constructor your implementation calls -- at the callsite.
Another reason is that it is easier in some cases to initialize the class within a function body, rather than using an initialization list.
I have a class which I intend to use for performing calculations. I declare one static object of the class elsewhere which I use to obtain results. The class has one public function apart from the constructor.
public:
double getProbability(PlayerStats &p1, PlayerStats &p2, Score &score);
As you can see, I have three objects as input parameters. My class then has two private functions which are called from getProbability(). One requires p1 and p2, the other requires all three of the parameters
My question is this. Is it better to pass these objects as parameters to the function or is it better to create private member variables and use these.
So for example
double MyClass::getProbability(PlayerStats &p1, PlayerStats &p2, Score &score){
otherFunction(p1,p2);
anotherFunction(p1,p2,score);
....
}
or
double MyClass::getProbability(PlayerStats &p1, PlayerStats &p2, Score &score){
this->p1 = p1;
this->p2 = p2;
this->score = score;
otherFunction(); //use member variables in these functions
anotherFunction();
....
}
It's better to pass them as parameters, as they don't really represent class state and storing them as members will probably be more performance costly than simply continuing to pass around the references.
But it doesn't really look like your class has any state at all, which leads me to believe all of these methods should be free-functions in a suitable namespace rather than members of a class (perhaps you come from a Java background?).
I prefer passing the parameter to the private functions. As far as your class may be access by multiple concurrent threads, it is better to send each data to its related function.
You should pass the arguments directly to your other methods. Even if other functions used them it would be very confusing because nothing in the function signature indicates that those arguments would be kept around.
If you need some of these parameters in other functions and those parameters remain the same through several calls, you could refactor your class. It would take the ones which stay the same in the constructor and then function calls just pass in the ones which will change. It really depends on the needs of your application to determine whether this is a better approach.