How can i use only 3rd argument (first and second arguments must be default)?
Like this:
double func(const double a = 5, const double b = 6, const double c = 7);
int main()
{
cout << "A = " << func(10) << endl << endl; //if i do like this, i'm using first argument, but not 3rd.
}
C++ doesn't support what you want to do currently. However, there are ways around it. You can use the Named Parameter Idiom or boost's Paremeter library.
I recommend the former. It's clearer, easier to debug, etc...
The only way to do this would be to swap the argument order:
double func(const double c = 7, const double a = 5, const double b = 6);
You could (possibly) use a few wrapper types and overloading, then use the types to name the parameter when calling:
struct A { double a; constexpr static double def = 5.0; };
struct B { double b; constexpr static double def = 6.0; };
struct C { double c; constexpr static double def = 7.0; };
double func(double a=A::def, double b=B::def, double c=C::def) { /* whatever */ }
double func(A a) { return func(a.a, B::def, C::def); }
double func(B b) { return func(A::def, b.b, C::def); }
double func(C c) { return func(A::def, B::def, c.c); }
int main()
{
func(A{3.0});
func(B{9.0});
func(C{12.0});
}
Related
Suppose I am trying to use a function which accepts a binary function and calls it with some arguments:
typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);
// Can't change this
double ExternalFunction(BinaryFunction binaryFunction)
{
return binaryFunction(1, 2);
}
Now suppose a user of my code is going to provide me with a unary function. My goal is to convert it into a binary function so that I can call ExternalFunction with it:
double MyFunction(UnaryFunction unaryFunction)
{
BinaryFunction binaryFunction = /* want a function (a, b) -> unaryFunction(a + b) */;
return ExternalFunction(binaryFunction);
}
How do I do this? Just to be clear, I understand that this would be easy if the unary function were known at compile time, but it's not - it will be an argument to my function. Thanks in advance.
Here's a summary of my attempts. I believe I understand why these don't work, but I'm providing them so you can see what I've been thinking so far.
I can't use a lambda, because I'd have to capture UnaryFunction, and capturing lambdas can't be converted to function pointers:
double MyFunction(UnaryFunction unaryFunction)
{
BinaryFunction binaryFunction = [unaryFunction](double a, double b){ return unaryFunction(a + b); };
return ExternalFunction(binaryFunction);
}
Use std::function ? Can't get that to work either:
void MyFunction(UnaryFunction unaryFunction)
{
std::function<double(double, double)> binaryFunctionTemp = [unaryFunction](double a, double b)
{
return unaryFunction(a + b);
};
BinaryFunction binaryFunction = binaryFunctionTemp.target<double(double, double)>();
ExternalFunction(binaryFunction);
}
What about a function object? Won't work because we'd need a pointer to a member function:
class BinaryFromUnary
{
public:
BinaryFromUnary(UnaryFunction unaryFunction) : unary_(unaryFunction) {};
double operator()(double a, double b)
{
return unary_(a + b);
}
private:
UnaryFunction unary_;
};
void MyFunction(UnaryFunction unaryFunction)
{
BinaryFromUnary functionObject(unaryFunction);
std::function<double(double, double)> binaryFunction = functionObject;
ExternalFunction(binaryFunction.target<double(double, double)>());
}
Even had a go with std::bind (and probably messed it up):
struct Converter {
Converter(UnaryFunction unary) : unary_(unary) {}
double binary(double a, double b) const { return unary_(a + b); }
UnaryFunction unary_;
};
void MyFunction(UnaryFunction unaryFunction)
{
Converter converter(unaryFunction);
std::function<double(double, double)> binaryFunction = std::bind( &Converter::binary, converter, _1, _2);
ExternalFunction(binaryFunction.target<double(double, double)>());
}
Tried a couple of other things along the same lines. Any ideas would be much appreciated.
Use an external variable to hold the unary function.
Include standard disclaimers about how inelegant and non-thread safe this is, etc. but at least this is a hack consistent with the stated requirements:
#include <iostream>
typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);
// Can't change this
double ExternalFunction(BinaryFunction binaryFunction) {
return binaryFunction(1, 2);
}
namespace foo {
thread_local UnaryFunction unaryFunction;
}
double MyBinaryFunction(double a, double b) {
return foo::unaryFunction(a + b);
}
double MyUnaryFunction(double a) {
return 2 * a;
}
double MyFunction(UnaryFunction unaryFunction) {
foo::unaryFunction = unaryFunction;
BinaryFunction binaryFunction = MyBinaryFunction;
return ExternalFunction(binaryFunction);
}
int main() {
std::cout << MyFunction(MyUnaryFunction) << std::endl; // 6
return 0;
}
I don't know your exact use-case, but there's a chance this might help you:
typedef double (*BinaryFunction)(double a, double b);
typedef double (*UnaryFunction)(double a);
// Can't change this
double ExternalFunction(BinaryFunction binaryFunction)
{
return binaryFunction(1, 2);
}
// If you always know the unary function at compile time:
// Create a wrapper function with the BinaryFunction signature that takes
// a unary function as a NTTP:
template <UnaryFunction unaryFunction>
double wrapper(double a, double b)
{
return unaryFunction(a + b);
}
// Simply use this wrapper to implement MyFunction as follows:
template <UnaryFunction unaryFunction>
double MyFunction()
{
return ExternalFunction(wrapper<unaryFunction>);
}
// Using it:
double unary1(double x) { return x * 2; }
double unary2(double x) { return x * 3; }
int main()
{
std::cout << MyFunction<unary1>() << '\n';
std::cout << MyFunction<unary2>() << '\n';
}
Have a godbolt link to play around with it as well.
Unlike the other answer, this doesn't require a global, but this also only works if you always know your function at compile-time, which there's a good chance you don't, so sorry in advance. Hope it was still interesting.
I'm trying to pass function of multiple arguments to other function. I know how to pass a function of single argument function to other function as it was described in C++ primer plus book.
However, I get an error when I'm trying to pass multiple arguments with class(poly_3d) to NR_method function.
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double));
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
NR_method(3.2, poly_3d);
system("PAUSE");
return 0;
}
double poly_3d(double x, constants cst) {
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
double NR_method(double a, double (*poly_3d)(double)) {
double c = (*poly_3d)(a);
return c;
}
So the error I'm getting is from NR_method(3.2, poly_3d) in main function. I know that if poly_3d was single arg, this would work.
If this is a horrible way to write codes, then any directions towards learning C++ more effectively for newbies would be much appreciated! Thanks
Take a look at the following code. We're using a template to make things look nicer.
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
/// Note that we take a ref now, no need to copy cst.
double poly_3d(double x, constants & cst)
{
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
/// Note that we take a ref now, no need to copy cst.
template <class F>
double NR_method(double a, constants & cst, F func)
{
return func(a, cst);
}
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
NR_method(3.2, cst, &poly_3d);
system("PAUSE");
return 0;
}
You are declaring the function poly_3d with 2 arguments but passing only one. I made a few changes on the code for you
#include <iostream>
#define log(x) std::cout<<x<<std::endl;
class constants {
public:
double A;
double B;
double C;
};
double poly_3d(double x, constants cst);
double NR_method(double a, constants cst, double(*poly_3d)(double, constants));
int main() {
constants cst;
cst.A = 2;
cst.B = -8;
cst.C = 10;
printf("%f", NR_method(3.2, cst, poly_3d));
system("PAUSE");
return 0;
}
double poly_3d(double x, constants cst) {
double y = 3 * cst.A*x*x + 2 * cst.B*x + cst.C;
return y;
}
double NR_method(double a, constants cst, double (*poly)(double, constants)) {
return (*poly)(a, cst);
}
Let's start by simplifying your code. (A minimal example removes distractions, allowing you to better focus on the actual issue.) It looks like you started to do this, but it can be taken further. After removing some stuff that is not needed to reproduce the compile error:
class constants {};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double));
int main() {
NR_method(3.2, poly_3d);
}
double poly_3d(double x, constants /*cst*/) {
return 3 * x;
}
double NR_method(double a, double (*poly_3d)(double)) {
return (*poly_3d)(a);
}
Now let's look at the error message:
error: invalid conversion from 'double (*)(double, constants)' to 'double (*)(double)'
This comes with an indication that the conversion is from poly_3d to the second argument of NR_method. If you look at those things, yes, that is the conversion you requested. The argument list for poly_3d is (double, constant), while the declared argument list for the second argument is just (double). There is a mismatch, which makes the conversion invalid. It's not all that different from the single-parameter case: the signatures must match. You can solve this by changing the argument's signature to math that of poly_3d.
Now, if you just make the signatures match, there is another problem in that NR_method does not have a constants value available. That is probably a logical error for you to work out. For a quick workaround to show the elimination of the compiler error, I'll add a local variable.
class constants {
};
double poly_3d(double x, constants cst);
double NR_method(double a, double(*poly_3d)(double, constants)); // <-- Desired signature
int main() {
NR_method(3.2, poly_3d);
}
double poly_3d(double x, constants /*cst*/) {
return 3.0 * x;
}
double NR_method(double a, double (*poly_3d)(double, constants)) {
constants cst; // <-- Allows this to compile, but probably not what you want.
return (*poly_3d)(a, cst); // <-- Needed a second parameter here.
}
There are ways to make this work nicer (for example, a std::function may be more convenient than a function pointer), but explaining those would fall outside the scope of this question, especially since some decisions would depend on the bigger picture.
I have a few functions that are very performance critical. They are quite generic and they depend on about 12 parameters apart from 2 inputs.
These parameters are fixed and I have 4 or 5 set of values (a1..a10) (b1..b10), etc... I could write the function a few times but for efficiency and maintainability I want to use non-type templates.
Imagine something like:
template <int a, int b, int c, int d, ..., int m>
double f(double x, double y)
{
return a*x+a*b*y+c+d+..+a*x*y; // some very complex math code
}
and it is only used in these N ways:
f<1,2,3,...,6>(x,y)
f<4,5,6,...,60>(x,y)
f<10,20,....,50,60>(x,y)
(in another application of the library, the set of parameters might be different but still only a few)
This is all fine but not very elegant...
I am looking for some "nicer" way to group these parameters in a cleaner way.
Ideas:
- create many PARAMS types full of constexpr[s]
- An abstract class with methods to be overriden (not sure if I can mix that with constexpr..)
I was wondering if there is some other nicer way or something available in boost that would be a good match for my problem.
EDIT:
Something similar to this would be perfect! (clearly this is NOT working). And the most important thing is that I need compile time evaluation.
#include <iostream>
struct Params1
{
constexpr static int a = 2;
constexpr static double b = 4;
constexpr static int c = 6;
};
struct Params2
{
constexpr static int a = 1;
constexpr static double b = 4.3;
constexpr static int c = 3;
};
template<P>
double f(double x)
{
return x*P.a*P.b*P.c;
};
int main() {
std::cout << f<Params1>(1.2) << std::endl;
std::cout << f<Params2>(1.2) << std::endl;
return 0;
}
Rewrite f() as follows and your last (post "edit") example should work
template <typename P>
double f(double x)
{
return x * P::a * P::b * P::c;
}
The points are
(a) change template <P> with template <typename P>
(b) and use P::a, P::b and P::c (static values inside a type) instead of P.a, P.b and P.c (values of an object)
Not sure to understand your requirement but...
These parameters are fixed and I have 4 or 5 set of values (a1..a10) (b1..b10), etc..
I suppose you could use std::integer_sequence and define 4 or 5 types
using set1 = std::integer_sequence<int, 1, 2, 3, ....>;
using set2 = std::integer_sequence<int, 2, 4, 6, ....>;
using set3 = std::integer_sequence<int, 10, 20, 30, ....>;
// ...
define the function this way
template <int a, int b, int c, int d, ..., int m>
double f (std::integer_sequence<int, a, ...> const &, double x, double y)
{ .. }
and call it as follows
f(set1{}, x, y);
f(set2{}, x, y);
f(set3{}, x, y);
// ...
The following is a full example (but only with 3 template integer)
#include <utility>
#include <iostream>
using set1 = std::integer_sequence<int, 1, 2, 3>;
using set2 = std::integer_sequence<int, 2, 4, 6>;
using set3 = std::integer_sequence<int, 10, 20, 30>;
template <int a, int b, int c>
double f(std::integer_sequence<int, a, b, c> const &, double x, double y)
{ return a*(x+y)+b*(x-y)+c*(y-x); }
int main ()
{
double x { 1.0 };
double y { 2.0 };
std::cout << f(set1{}, x, y) << std::endl; // print 4
std::cout << f(set2{}, x, y) << std::endl; // print 8
std::cout << f(set3{}, x, y) << std::endl; // print 40
}
Your given example code works quite well with some minor changes. Maybe thats what you are searching for?
struct Params1
{
constexpr static int a = 2;
constexpr static double b = 4;
constexpr static int c = 6;
};
struct Params2
{
constexpr static int a = 2;
constexpr static double b = 4;
constexpr static int c = 6;
};
template<typename P>
double f(double x)
{
return x*P::a*P::b*P::c;
}
int main() {
std::cout << f<Params1>(1.2) << std::endl;
std::cout << f<Params2>(1.2) << std::endl;
return 0;
}
I'm reading the book by Daoqi Yang "C++ and Object Oriented Numeric Computing for Scientists and Engineers". He has a similar example to what I am showing below, but the exceptions are the class "P" I define and the second to last line (which doesn't work). My question is: why does my compiler generate and error when I supply the function member f.integrand? What can I do to correct this? The errors being generated are C3867, C2440, and C2973.
Here is the code:
class P{
public:
double integrand(double x){
return (exp(-x*x));
}
};
template<double F(double)>
double trapezoidal(double a, double b, int n)
{
double h=(b-a)/n;
double sum=F(a)*0.5;
for(int i=1;i<n;i++)
{
sum+=F(a+i*h);
}
sum+=F(b)*0.5;
return (sum*h);
}
double integrand2(double x){
return (exp(-x*x));
}
int main(){
P f;
cout<< trapezoidal<integrand2>(0,1,100)<<endl; // this works
cout<< trapezoidal<f.integrand>(0,1,100)<<endl; // this doesn't work
}
Template arguments must be compile-time constant expressions or types, and member functions require special handling anyway. Instead of doing this, use boost::function<> as an argument, and boost::bind to create the functor, e.g.
double trapezoidal(double, double, boost::function<double(double)>);
// ...
P f;
trapezoidal(0, 1, 100, integrand2);
trapezoidal(0, 1, 100, boost::bind(&P::integrand, boost::ref(f)));
If you have 0x-capable compiler, you can use std::function and std::bind instead.
Cat Plus Plus is correct - boost::bind is a good way to do this easily. I've also included an alternate solution with the following snippet of code:
class P{
private:
double a;
public:
double integrand(double x){
return (a*exp(-x*x));
}
void setA(double y){
a = y;
}
void getA(){
cout<<a<<endl;
}
struct integrand_caller {
P* p;
integrand_caller(P& aP) : p(&aP) {};
double operator()(double x) const {
return p->integrand(x);
};
};
};
template <typename Evaluator, typename VectorType>
VectorType trapezoidal(Evaluator f, const VectorType& a, const VectorType& b, int n)
{
VectorType h=(b-a)/n;
VectorType sum=f(a)*0.5;
for(int i=1;i<n;i++)
{
sum+=f(a+i*h);
}
sum += f(b)*0.5;
return (sum*h);
}
double integrand2(double x){
return (exp(-x*x));
}
int main(){
P f[5];
for(int i=0;i<5;i++){
f[i].setA(5*i);
f[i].getA();
cout<< trapezoidal(P::integrand_caller(f[i]),(double)0, (double)1, 100) << endl;
cout<<trapezoidal(boost::bind(&P::integrand,f[i],_1), 0.0, 1.0, 100)<<"\n"<<endl;
}
}
The following uses a simple function pointer, but what if I want to store that function pointer? In that case, what would the variable declaration look like?
#include <iostream>
#include <vector>
using namespace std;
double operation(double (*functocall)(double), double wsum);
double get_unipolar(double);
double get_bipolar(double);
int main()
{
double k = operation(get_bipolar, 2); // how to store get_bipolar?
cout << k;
return 0;
}
double operation(double (*functocall)(double), double wsum)
{
double g = (*functocall)(wsum);
return g;
}
double get_unipolar(double wsum)
{
double threshold = 3;
if (wsum > threshold)
return threshold;
else
return threshold;
}
double get_bipolar(double wsum)
{
double threshold = 4;
if (wsum > threshold)
return threshold;
else
return threshold;
}
You code is almost done already, you just seem to call it improperly, it should be simply
double operation(double (*functocall)(double), double wsum)
{
double g;
g = functocall(wsum);
return g;
}
If you want to have a variable, it's declared in the same way
double (*functocall2)(double) = get_bipolar;
or when already declared
functocall2 = get_bipolar;
gives you a variable called functocall2 which is referencing get_bipolar, calling it by simply doing
functocall2(mydouble);
or passing it to operation by
operation(functocall2, wsum);
You already (almost) have it in your code:
double (*functocall)(double) = &get_bipolar;
This defines a function pointer named functocall which points to get_bipolar.
typedef double (*func_t)(double);
func_t to_be_used = get_bipolar
typedef double (*PtrFunc)(double);
PtrFunc ptrBipolar = get_bipolar;
OR
typedef double (Func)(double);
Func *ptrBipolar = get_bipolar;
which ever you are comfortable to use.
Have a look at boost function, it's a header only library that tidies things up a little (IMHO):
http://www.boost.org/doc/libs/1_42_0/doc/html/function.html
typedef boost::function<double (double)> func_t;
func_t to_be_used = &get_bipolar;
(NB: different syntax required for VC6)
double (*foo)(double);
where foo is the variable name.
You should consider using a typedef:
typedef double (*MyFunc)(double);
MyFunc ptr_func = &get_bipolar;
(*ptr_func)(0.0);
double operation(MyFunc functocall, double wsum)
{
double g;
g = (*functocall)(wsum);
return g;
}
May I recommend also the identity template trick:
template<class T>
class Id
{
typedef T type;
};
Id<double(double)>::type * ptr_func = &get_bipolar;
MyFunc func = &get_bipolar;
(*ptr_func)(0.0);
double operation(Id<double(double)>::type * functocall, double wsum)
{
double g;
g = (*functocall)(wsum);
return g;
}