How do I store a function to a variable? - c++

I think they are called functors? (it's been a while)
Basically, I want to store a pointer to a function in a variable, so I can specify what function I want to use from the command line.
all the functions return and take the same values.
unsigned int func_1 (unsigned int var1)
unsigned int func_2 (unsigned int var1)
function_pointer = either of the above?
so then I could call it by going: function_pointer(my_variable)?
EDIT:
as per #larsmans's suggestion, I've gotten this:
Config.h:
class Config
{
public:
unsigned static int (*current_hash_function)(unsigned int);
};
Config.cpp:
#include "Config.h"
#include "hashes.h"
unsigned static int (*current_hash_function)(unsigned int) = kennys_hash_16;
hashes.h:
unsigned int kennys_hash(unsigned int out);
unsigned int kennys_hash_16(unsigned int out);
hashes.cpp:
just implements the functions in the header
main.cpp:
#include "Config.h"
#include "hashes.h"
// in test_network:
unsigned int hashed = Config::current_hash_function(output_binary);
//in main():
else if (strcmp(argv[i], "-kennys_hash_16") == 0)
{
Config::current_hash_function = kennys_hash_16;
}
else if (strcmp(argv[i], "-kennys_hash_8") == 0)
{
Config::current_hash_function = kennys_hash;
}
the error I get:
g++ -o hPif src/main.o src/fann_utils.o src/hashes.o src/Config.o -lfann -L/usr/local/lib
Undefined symbols:
"Config::current_hash_function", referenced from:
test_network() in main.o // the place in the code I've selected to show
auto_test_network_with_random_data(unsigned int, unsigned int, unsigned int)in main.o
generate_data(unsigned int, unsigned int, unsigned int)in main.o
_main in main.o // the place in the code I've selected to show
_main in main.o // the place in the code I've selected to show
generate_train_file() in fann_utils.o
ld: symbol(s) not found
collect2: ld returned 1 exit status
make: *** [hPif] Error 1

The simplest you can do is
unsigned int (*pFunc)(unsigned int) = func_1;
This is a bare function pointer, which cannot be used to point to anything other than a free function.
You can make it less painful if your compiler supports the C++0x auto keyword:
auto pFunc = func_1;
In any case, you can call the function with
unsigned int result = pFunc(100);
There are many other options that provide generality, for example:
You can use boost::function with any C++ compiler
With a compiler implementing features of C++0x you can use std::function
These can be used to point to any entity that can be invoked with the appropriate signature (it's actually objects that implement an operator() that are called functors).
Update (to address updated question)
Your immediate problem is that you attempt to use Config::current_hash_function (which you declare just fine) but fail to define it.
This defines a global static pointer to a function, unrelated to anything in class Config:
unsigned static int (*current_hash_function)(unsigned int) = kennys_hash_16;
This is what you need instead:
unsigned int (*Config::current_hash_function)(unsigned int) = kennys_hash_16;

From C++11 you can use std::function to store functions. To store function you use it as follsonig:
std::function<return type(parameter type(s))>
as an example here it is:
#include <functional>
#include <iostream>
int fact (int a) {
return a > 1 ? fact (a - 1) * n : 1;
}
int pow (int b, int p) {
return p > 1 ? pow (b, p - 1) * b : b;
}
int main (void) {
std::function<int(int)> factorial = fact;
std::function<int(int, int)> power = pow;
// usage
factorial (5);
power (2, 5);
}

No, these are called function pointers.
unsigned int (*fp)(unsigned int) = func_1;

You could also use function either from the c++0x or from boost.
That would be
boost::function<int(int)>
and then use bind to bind your function to this type.
Have a look here and here
Ok here would be a example. I hope that helps.
int MyFunc1(int i)
{
std::cout << "MyFunc1: " << i << std::endl;
return i;
}
int MyFunc2(int i)
{
std::cout << "MyFunc2: " << i << std::endl;
return i;
}
int main(int /*argc*/, char** /*argv*/)
{
typedef boost::function<int(int)> Function_t;
Function_t myFunc1 = boost::bind(&MyFunc1, _1);
Function_t myFunc2 = boost::bind(&MyFunc2, _1);
myFunc1(5);
myFunc2(6);
}

You can store a function in a variable in c++ in this way
auto function_name = [&](params){
statements
};
auto add = [&](int a,int b){
return a+b;
};
cout<<add(5,6);

typedef unsigned int (*PGNSI)(unsigned int);
PGNSI variable1 = func_1;
PGNSI variable2 = func_2;

unsigned int (* myFuncPointer)(unsigned int) = &func_1;
However, the syntax for function pointers is awful, so it's common to typedef them:
typedef unsigned int (* myFuncPointerType)(unsigned int);
myFuncPointerType fp = &func_1;

IF you have Boost installed, you can also check out Boost Function.

Related

Issue with the return type of the `get_mpz_t` function of GNU MP

The GNU MP manual specifies the declaration of the function get_mpz_t:
Function: mpz_t mpz_class::get_mpz_t ()
So I was expecting a mpz_t return type. But running the simple code:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpz_class n;
n = "12345678901234567890123456789012345678901234567890";
mpz_t m;
mpz_init(m);
m = n.get_mpz_t();
gmp_printf("m %Zd\n", m);
}
Compiled with
g++ mpz_test.cc -o mpz_test -lgmpxx -lgmp
Produces the error output at line m = n.get_mpz_t():
mpz_split.cc: In function ‘int main()’:
mpz_split.cc:12:4: error: incompatible types in assignment of ‘mpz_ptr {aka __mpz_struct*}’ to ‘mpz_t {aka __mpz_struct [1]}’
m = n.get_mpz_t();
^
Looking at the gmpxx.h code I find the declarations:
// conversion functions
mpz_srcptr __get_mp() const { return mp; }
mpz_ptr __get_mp() { return mp; }
mpz_srcptr get_mpz_t() const { return mp; }
mpz_ptr get_mpz_t() { return mp; }
And, of course, mpz_ptr is defined in gmp.h
typedef __mpz_struct *mpz_ptr;
So, is the manual inaccurate? Or, what am I doing wrong here?
The problem occurs on this line:
m = n.get_mpz_t();
You cannot assign to mpz_t directly, instead use mpz_set():
mpz_set(m, n.get_mpz_t());
So, your code should look like this:
#include <iostream>
#include <gmpxx.h>
using namespace std;
int main (void) {
mpz_class n;
n = "12345678901234567890123456789012345678901234567890";
mpz_t m;
mpz_init(m);
mpz_set(m, n.get_mpz_t()); // correct assignment
gmp_printf("m %Zd\n", m);
}

Create MPI reduction operator from c++ lambda function

I would like to write a function that wraps MPI_Allreduce, and which accepts any binary operator (as std::reduce) to be used as reduction operator by MPI. Especially, the user of such a function could use a lambda.
The following simple sample code illustrates that:
#include <mpi.h>
#include <iostream>
#include <functional>
template<typename BinaryOp>
void reduce(double *data, int len, BinaryOp op) {
auto lambda=[op](void *a, void *b, int *len, MPI_Datatype *){
double *aa=static_cast<double *>(a);
double *bb=static_cast<double *>(bb);
for (int i=0; i<*len; ++i) {
bb[i]=op(aa[i], bb[i]);
}
};
// MPI_User_function is a typedef to: void (MPI_User_function) ( void * a, void * b, int * len, MPI_Datatype * )
MPI_User_function *opPtr=/* black magic code that get the function pointer from the lambda */;
MPI_Op mpiOp;
MPI_Op_create(*opPtr, 1, &mpiOp);
MPI_Allreduce(MPI_IN_PLACE, data, len, MPI_DOUBLE, mpiOp, MPI_COMM_WORLD);
MPI_Op_free(&mpiOp);
}
int main() {
MPI_Init(nullptr, nullptr);
double data[4]={1.,2.,3.,4.};
reduce(data, 4, [](double a, double b){return a+b;});
int pRank;
MPI_Comm_rank(MPI_COMM_WORLD, &pRank);
if (pRank==0) {
for (int i=0; i<4; ++i) {
std::cout << data[i] << " ";
}
std::cout << std::endl;
}
MPI_Finalize();
return 1;
}
The missing part is the code that get a function pointer from the lambda in the reduce function. From several related questions, this problem of getting a function pointer from a capturing lambda seems to be tricky but possible to solve. But I failed to have something working on this simple code (I tried some tricks with std::function, std::bind, storage of the lambda in a static variable)... So a little help would be great!
EDIT: Following #noma answer, I tried the following simplified code without MPI in goldbolt
#include <iostream>
#include <functional>
typedef double MPI_Datatype;
template<typename BinaryOp, BinaryOp op> // older standards
void non_lambda(void *a, void *b, int *len, MPI_Datatype *)
{}
template<typename BinaryOp>
void reduce(double *data, int len, BinaryOp op) {
typedef void (MPI_User_function) ( void * a, void * b, int * len, MPI_Datatype * );
MPI_User_function *opPtr = &non_lambda<decltype(+op), +op>; // older standards;
}
int main() {
double data[4]={1.,2.,3.,4.};
reduce(data, 4, [](double a, double b){return a+b;});
return 1;
}
It compile on some compilers. Here are the results:
icc >= 19.0.1 (with -std=c++17) : OK
clang++ >= 5.0.0 (with --std=c++17): OK
clang++ 10.0.0 (with --std=c++14): NOK
g++ 9.3 (with --std=c++17): NOK
icc >= 19.0.0 (with -std=c++17) : NOK
The error message with icc 19.0.0 with -std=c++17 (or icc 19.0.1 with -std=c++14) is interesting:
<source>(15): error: expression must have a constant value
MPI_User_function *opPtr = &non_lambda<decltype(+op), +op>; // older standards;
^
detected during instantiation of "void reduce(double *, int, BinaryOp) [with BinaryOp=lambda [](double, double)->double]" at line 21
And indeed, I don't really understand the passing of the 'op' variable which is a runtime argument of the function reduce as the second template parameter of the non_lambda function... Is it an obscure c++17 functionality that only some of the compilers support?
I think the lambda approach is not possible here as it is a capturing lambda, see
https://stackoverflow.com/a/28746827/7678171
We can use a function template with the BinaryOp as a template value parameter instead of a Lambda here. This assumes that the BinaryOp is either a function pointer, or a capture-less lambda, that can be converted into one. Instead of the lambda inside your reduce we introduce:
template<auto op> // this is C++17, so use --std=c++17
// template<typename BinaryOp, BinaryOp op> // older standards
void non_lambda(void *a, void *b, int *len, MPI_Datatype *)
{
double *aa=static_cast<double *>(a);
double *bb=static_cast<double *>(bb);
for (int i=0; i<*len; ++i) {
bb[i]=op(aa[i], bb[i]);
}
}
The Black Magic line then is:
/* black magic code that get the function pointer from the lambda */
MPI_User_function *opPtr = &non_lambda<+op>; // NOTE: the + implies the lamda to function pointer conversion here
// MPI_User_function *opPtr = &non_lambda<decltype(+op), +op>; // older standards;
Hope this helps.
NOTE: I got this compiled using Clang 6.0, but g++ 7.5 failed (possible compiler bug?):
error: no matches converting function ‘non_lambda’ to type ‘void (*)(void*, void*, int*, struct ompi_datatype_t**)’
MPI_User_function *opPtr = &non_lambda<+op>;
^~~~~
note: candidate is: template<auto op> void non_lambda(void*, void*, int*, ompi_datatype_t**)
void non_lambda(void *a, void *b, int *len, MPI_Datatype *)
Maybe newer g++ versions work.

linking template metaprogramming issue with g++

I am porting some windows code that compiles like would expect under msvc 10, but I am having trouble with it linking under g++ 4.8 and/or clang 3.5.
masks.h
#ifndef MASKS_H
#define MASKS_H
#include <boost/array.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/preprocessor/repetition/repeat.hpp>
namespace MASKS
{
// ------------------------------------------------- power function
template<class TYPE, uint32_t Base, uint32_t Power>
struct Pow
{
static const TYPE tmp = Pow<TYPE, Base, Power / 2>::value;
static const TYPE value = (Power % 2 == 0) ? (tmp * tmp) : (Base * tmp * tmp);
};
template<class TYPE, uint32_t Base>
struct Pow<TYPE, Base, 0>
{
static const TYPE value = 1;
};
template<class TYPE, uint32_t Base>
struct Pow<TYPE, Base, 1>
{
static const TYPE value = Base;
};
// ------------------------------------------------- mask function
template<class TYPE, int Val>
struct Mask
{
static const TYPE value = Pow<TYPE, 2, Val>::value - 1;
};
template<class TYPE>
struct Mask<TYPE, 64>
{
static const TYPE value = 0xffffffffffffffff;
};
//#define MASK(z, n, text) (MASKS::Mask<uint64_t, n>::value)
static const boost::array<uint64_t, 4> s_Masks =
boost::assign::list_of<uint64_t>
(MASKS::Mask<uint64_t, 0>::value)
(MASKS::Mask<uint64_t, 1>::value)
(MASKS::Mask<uint64_t, 2>::value)
(MASKS::Mask<uint64_t, 3>::value)
//BOOST_PP_REPEAT_FROM_TO (0, 65, MASK, text)
;
inline uint64_t GetMask (size_t iLen) { return MASKS::s_Masks[iLen]; }
} // namespace MASKS
#endif // MASKS_H
main.c
#include <iostream>
#include "masks.h"
int main (int /*argc*/, char */*argv*/[])
{
std::cout << "63 bit mask: " << std::hex << std::showbase << MASKS::GetMask (63) << std::endl;
return 0;
}
When I compile it will not link and gives the following error:
g++ masks.cpp -o mask -std=c++11 -pedantic -Wall -Wextra
tmp/ccYZ0MMb.o: In function `__static_initialization_and_destruction_0(int, int)':
masks.cpp:(.text+0xd9): undefined reference to `MASKS::Mask<unsigned long long, 0>::value'
masks.cpp:(.text+0xea): undefined reference to `MASKS::Mask<unsigned long long, 1>::value'
masks.cpp:(.text+0xfe): undefined reference to `MASKS::Mask<unsigned long long, 2>::value'
masks.cpp:(.text+0x10f): undefined reference to `MASKS::Mask<unsigned long long, 3>::value'
collect2: error: ld returned 1 exit status
I am not sure what I am forgetting here. I expected the TMP objects/functions to get translated to values by the compiler and stored in the array of masks I am trying to build. I am rusty on my g++ syntax I guess. Can anyone see what I've done wrong?
Thanks.

C++: Undefined reference to function in namespace

Here I am, trying to figure out what's wrong with my code without success :(
I'm writing a resampler but I guess that's of no interest at all, I'm just trying yo make this stupid warning go away. Anyway, here's my code:
ddc.hpp
#ifndef __DIGITAL_DOWN_CONVERTER_H__
#define __DIGITAL_DOWN_CONVERTER_H__
#include <vector>
#include "interpolator.h"
namespace ddc {
void decimate(std::vector<float> &, unsigned int);
void expand(std::vector<float> &, unsigned int);
void perform_resampling(std::vector<float>, unsigned int, unsigned int);
void generate_filter(std::vector<float> &, unsigned int, unsigned int);
float Sinc(float);
unsigned int mcd(unsigned int, unsigned int);
}
#endif
ddc.cpp
#include "ddc.hpp"
namespace ddc {
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
unsigned int i, gcd = mcd(freq_1, freq_2);
unsigned int downFactor, upFactor;
std::vector<float> filter;
downFactor = freq_1/gcd;
upFactor = freq_2/gcd;
generate_filter(filter, 1024 /* lobi della semi-sinc */, upFactor);
decimate(data, downFactor);
expand(data, upFactor);
interpolate_fft(data, filter);
}
}
main.cpp
#include <vector>
#include "ddc.hpp"
using namespace std;
int main() {
vector<float> data;
// bla bla
ddc::perform_resampling(data, 1000000, 60000);
return 0;
}
Compiling with g++ (linux) I get the following error:
$ make all
g++ -c ddc.cpp -o ddc.o -Wall -O3 -lm -m64
g++ -c main.cpp -o main.o -Wall -O3 -lm -m64
g++ ddc.o main.o -o ../bin/resampler
main.o: In function `main':
main.cpp:(.text.startup+0x255): undefine d reference to
`ddc::perform_resampling(std::vector<float, std::allocator<float> >, unsigned int, unsigned int)'
collect2: ld returned 1 exit status
make: *** [../bin/resampler] Error 1
I'm going out of my mind, please help me! What am I doing wrong? Besides, If I remove ddc:: from the main function, gcc suggests me this:
main.cpp:59:49: note: suggested alternative:
ddc.hpp:24:7: note: ‘ddc::perform_resampling’
You declare a function taking a vector by value as its first argument, then define it taking the vector by reference. This produces a separate overload, and the declared function has no definition. Presumably it should be a reference, so add & to the declaration in the header.
You would get a more useful compiler error if you defined functions outside their namespace:
void ddc::perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
// ^^^^^
// blah blah
}
since it's an error to define a function with a qualified name if it hasn't been declared.
These two are different:
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2)
void perform_resampling(std::vector<float> data, unsigned int freq_1, unsigned int freq_2)
P.S. This shows one good reason to put parameter names in your prototypes, even though they aren't strictly required. With parameter names, you can compare a prototype directly to a definition, and they should match character for character
In your prototype, you are missing &
void perform_resampling(std::vector<float>, unsigned int, unsigned int);
It appears in the definition
void perform_resampling(std::vector<float> &data, unsigned int freq_1, unsigned int freq_2) {
unsigned int i, gcd = mcd(freq_1, freq_2);
unsigned int downFactor, upFactor;
std::vector<float> filter;
downFactor = freq_1/gcd;
upFactor = freq_2/gcd;
generate_filter(filter, 1024 /* lobi della semi-sinc */, upFactor);
decimate(data, downFactor);
expand(data, upFactor);
interpolate_fft(data, filter);
}

Undefined reference to static function pointer member in c++, what am I doing wrong?

please consider these files:
p.h:
#ifndef _p_h_
#define _p_h_
class p{
public:
static void set_func(int(*)());
private:
static int (*sf)();
};
#endif
p.cpp:
#include "p.h"
#include <cstdio>
int (p::*sf)() = NULL; //defining the function pointer
void p::set_func(int(*f)()){
sf = f;
}
main.cpp:
#include "p.h"
#include <iostream>
int function_x(){
std::cout << "I'm function_x()" << std::endl;
return 1234;
}
int main(){
p::set_func(function_x);
}
when compiling, I get this:
$ g++ -o pp main.cpp p.cpp
/tmp/ccIs0M7r.o:p.cpp:(.text+0x7): undefined reference to `p::sf'
collect2: ld returned 1 exit status
but:
$ g++ -c -o pp p.cpp
compiles right.
What's wrong with the code? I just can't find where the problem is, please your help will be more than appreciated.
Thanks.
Your attempt at defining p::sf is incorrect – yours is a definition of a global variable named sf that is of type int (p::*)(), i.e. a pointer to a member function. Consequently p::sf remains undefined, hence the linker error.
Try this instead:
int (*p::sf)() = 0;
// or,
typedef int (*p_sf_t)();
p_sf_t p::sf = 0;
The difference is because error only occurs when you actually link the program. The problem is in your declaration of the static function pointer. The correct syntax is:
int (*p::sf)() = NULL; //defining the function pointer
You define a member function pointer and not a function pointer. I'm not sure what the correct syntax is, but I would have tried something like this:
int (*p::sf)() = NULL;
I will not give another answer (ildjarn answer is correct) but i will suggest you another way of achieving the same without static initialization (and the burdens it implies)
class p{
public:
typedef int (*func_t)();
static void set_func(func_t v) {
func_t& f = getFuncRef();
f = v;
}
static void call_func() {
func_t& f = getFuncRef();
assert( f != 0);
f();
}
private:
static func_t& getFuncRef() {
static func_t sf = 0;
return sf;
}
};
in this way you delegate the static initialization to a static function variable, which doesn't have the initialization order problems that affect static data variables, and is lazy-initialised