template <int N>
struct Factorial {
enum { value = N * Factorial<N - 1>::value };
};
template <>
struct Factorial<0> {
enum { value = 1 };
};
const int x = Factorial<4>::value; // == 24
const int y = Factorial<0>::value; // == 1
After pre-compilation, if we could magically see what the compiler produced, would we actually see:
const int x = 24;
const int y = 1;
And would we see actual definitions for the struct Factorial, multiple of these? If so how would they look? I'm trying wrap my head around this part of the metaprogramming process.
Using g++ -fdump-tree-original on this code, I see the following result, which for this case seems to confirm your suspicion:
;; Function int main() (null)
;; enabled by -tree-original
{
const int x = 24;
const int y = 1;
<<cleanup_point const int x = 24;>>;
<<cleanup_point const int y = 1;>>;
}
return <retval> = 0;
Related
I have a function which takes in two int values, does some processing and then returns the processed values in the form of a struct to the calling function.
The following is my called function:
auto start_end(){
bool cond = false;
int xd = 0;
int yd = 0;
std::cout<<("Please enter a desired x coordinate")<<std::endl;
std::cin>>xd;
while(std::cin.fail()){
std::cout<<("That is not a valid integer. Please enter a valid x co-ordinate")<<std::endl;
std::cin.clear();
std::cin.ignore(256,'\n');
std::cin>>xd;
}
std::cout<<("Please enter a desired y coordinate")<<std::endl;
std::cin>>yd;
while(std::cin.fail()){
std::cout<<("That is not a valid integer. Please enter a valid y co-ordinate")<<std::endl;
std::cin.clear();
std::cin.ignore(256,'\n');
std::cin>>yd;
}
struct xy{int x_received; int y_received;};
return xy{xd,yd};
}
We can see that the struct xy returns two values xd, yd in the above function start_end().
The following is my calling function:
int main(int argc, const char * argv[]) {
std::cout <<("A-Star-Algorithm for Project 2 obstacle map")<<std::endl;
int x_start = 0;
int y_start = 0;
int init_point = start_end();
return 0;
}
So when I try to store the return values xd, yd in the variable init_point, I get the error:
No viable conversion from 'xy' to 'int'
Since, I got this error I tried to write the receiving variable as a 2 - index array:
int init_point[2] = start_end();
When I try to do in this way, I get the following error:
Array initializer must be an initializer list
My exact question : What is the appropriate manner in which I have to receive the values xd and yd returned by function start_end() when it is called inside function int main() ?
You need to move your struct into a place that can be seen by start_end and main:
struct xy { int x; int y; };
xy start_end()
{
...
return { xd, yd };
}
int main()
{
}
Then you can either assign it with auto or use the type name xy:
int main()
{
auto xy1 = start_end();
xy xy2 = start_end();
}
Or you can use std::pair or std::tuple.
std::tuple is to your relief (live)
#include <iostream>
#include <tuple>
auto start_end() {
auto x = 1, y = 2;
return std::make_tuple(x, y);
}
int main() {
int x, y;
std::tie(x, y) = start_end();
std::cout << x << ' ' << y << std::endl;
}
This is a follow-up question to
mem_fn to function of member object
This is the current code.
#include <vector>
#include <algorithm>
#include <functional>
struct Int
{
Int(int _x = 0) : x(_x) {}
int GetInt() const { return x; }
int x;
};
struct IntWrapper
{
IntWrapper(int _x = 0) : test(_x) {}
int GetWrappedInt() const { return test.GetInt(); }
Int test;
};
template<class ContainerT, class Mem> constexpr auto maxElem(const ContainerT& _container, Mem _Pm)
{
auto memFn = std::mem_fn(_Pm);
return memFn(std::max_element(_container.cbegin(), _container.cend(), [&](auto _rhs, auto _lhs) { return memFn(_rhs) < memFn(_lhs); }));
}
int main()
{
{
std::vector<Int> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i * 11 % 7); // some random values
}
int m = maxElem(vec, &Int::GetInt);
int n = maxElem(vec, &Int::x);
}
{
std::vector<IntWrapper> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i * 7 % 11); // some random values
}
int m = maxElem(vec, &IntWrapper::GetWrappedInt);
//int o = maxElem(vec, ???) // what if GetWrappedInt didn't exist?
}
return 0;
}
The original question was about retrieving the x value of the Int struct through anIntWrapper object. I used mem_fn for this because it doesn't seem to distinguish between a function returning an int and an int member variable (Seen in these lines:
int m = maxElem(vec, &Int::GetInt);
int n = maxElem(vec, &Int::x);
The solution for IntWrapper objects was to add .test
auto y = std::mem_fn(&Int::GetInt);
auto b = y(wrapper.test);
to the call. However, in the maxElem function, I cannot do this.
I'm wondering if there is a way to formulate the call in such a way that the mem_fn goes from the IntWrapper object directly to the int x variable (Without the helper function and assuming that all members are public).
//int o = maxElem(vec, ???) // what if GetWrappedInt didn't exist?
The original approach was auto y = std::mem_fn(&IntWrapper::test.GetInt); // ERROR, which of course does not compile, but shows the idea.
Thanks in advance!
You cannot use std::mem_fn with something different than a pointer to member (such as a pointer to member of member). So, you must use that. In your particular case, you can achieve that with
std::vector<IntWrapper> vec;
for (int i = 0; i < 10; ++i)
{
vec.push_back(i * 11 % 7); // some random values
}
auto m = maxElem(vec, &IntWrapper::GetWrappedInt);
However, I strongly advise you to use lambda expressions whenever possible. std::mem_fn should be considered as if deprecated, since, AFAIK, it serves no purpose that cannot be achieved at least as well by other means, i.e. a lambda.
i have this code which uses a function pointer to point 3 functions sum, subtract, mul. it works well. but now the problem is that i have functions with different no.of parameters and different data types. how to implement this.
int add(int a, int b)
{
cout<<a+b;
}
int subtract(int a, int b)
{
cout<<a-b;
}
int mul(int a, int b)
{
cout<<a*b;
}
int main()
{
int (*fun_ptr_arr[])(int, int) = {add, subtract, mul};
unsigned int ch, a = 15, b = 10,c=9;
ch=2;
if (ch > 4) return 0;
(*fun_ptr_arr[ch])(a, b);
return 0;
}
The simple answer is that technically you can't do this. You could do some manipulations using an array as input for all these functions, but you will still have to know exactly what to pass to each function. From a software engineering perspective, you should not do this - I suggest you take a look at the nice answers here: C++ Function pointers with unknown number of arguments
A slightly different approach using objects to implement the required behavior. In order to have a truly generic kind of solution, we need to use Interfaces.
Dismantle the data and operation i.e keep them separately.
//Interface which describes any kind of data.
struct IData
{
virtual ~IData()
{
}
};
//Interface which desribes any kind of operation
struct IOperation
{
//actual operation which will be performed
virtual IData* Execute(IData *_pData) = 0;
virtual ~IOperation()
{
}
};
Now, every operation knows the kind of data it work on and will expect that kind of data only.
struct Operation_Add : public IOperation
{
//data for operation addition.
struct Data : public IData
{
int a;
int b;
int result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Add::Data_Add"
Operation_Add::Data *pData = dynamic_cast<Operation_Add::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = pData->a + pData->b;
return pData;
}
};
struct Operation_Avg : public IOperation
{
//data for operation average of numbers.
struct Data : public IData
{
int a[5];
int total_numbers;
float result;
};
IData* Execute(IData *_pData)
{
//expected data is "Operation_Avg::Data_Avg"
Operation_Avg::Data *pData = dynamic_cast<Operation_Avg::Data*>(_pData);
if(pData == NULL)
{
return NULL;
}
pData->result = 0.0f;
for(int i = 0; i < pData->total_numbers; ++i)
{
pData->result += pData->a[i];
}
pData->result /= pData->total_numbers;
return pData;
}
};
Here, is the operation processor, the CPU.
struct CPU
{
enum OPERATION
{
ADDITION = 0,
AVERAGE
};
Operation_Add m_stAdditionOperation;
Operation_Avg m_stAverageOperation;
map<CPU::OPERATION, IOperation*> Operation;
CPU()
{
Operation[CPU::ADDITION] = &m_stAdditionOperation;
Operation[CPU::AVERAGE] = &m_stAverageOperation;
}
};
Sample:
CPU g_oCPU;
Operation_Add::Data stAdditionData;
stAdditionData.a = 10;
stAdditionData.b = 20;
Operation_Avg::Data stAverageData;
stAverageData.total_numbers = 5;
for(int i = 0; i < stAverageData.total_numbers; ++i)
{
stAverageData.a[i] = i*10;
}
Operation_Add::Data *pResultAdd = dynamic_cast<Operation_Add::Data*>(g_oCPU.Operation[CPU::ADDITION]->Execute(&stAdditionData));
if(pResultAdd != NULL)
{
printf("add = %d\n", pResultAdd->result);
}
Operation_Avg::Data *pResultAvg = dynamic_cast<Operation_Avg::Data*>(g_oCPU.Operation[CPU::AVERAGE]->Execute(&stAverageData));
if(pResultAvg != NULL)
{
printf("avg = %f\n", pResultAvg->result);
}
If you have the following functions
int f1(int i);
int f2(int i, int j);
You can define a generic function type like this
typedef int (*generic_fp)(void);
And then initialize your function array
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
But you will have to cast the functions back
int result_f1 = ((f1) func_arr[0]) (2);
int result_f2 = ((f2) func_arr[1]) (1, 2);
Obviously, it does not look like a good way to build a program
To make code look a little bit better you can define macros
#define F1(f, p1) ((f1)(f))(p1)
#define F2(f, p1, p2) ((f2)(f))(p1, p2)
int result_f1 = F1(func_arr[0], 2);
int result_f2 = F2(func_arr[1], 1, 2);
EDIT
Forgot to mention, you also have to define a type for every type of function
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
And to then cast stored pointers to those types
int result_f1 = ((fi) func_arr[0]) (2);
int result_f2 = ((fii) func_arr[1]) (1, 2);
Here is a complete example
#include <iostream>
typedef int (*generic_fp)(void);
typedef int (*fi)(int); // type for function of one int param
typedef int (*fii)(int, int); // type for function of two int params
#define F1(f, p1) ((fi)(f))(p1)
#define F2(f, p1, p2) ((fii)(f))(p1, p2)
int f1(int i);
int f2(int i, int j);
int main()
{
generic_fp func_arr[2] = {
(generic_fp) f1,
(generic_fp) f2
};
int result_f1_no_macro = ((fi) func_arr[0]) (2);
int result_f2_no_macro = ((fii) func_arr[1]) (1, 2);
int result_f1_macro = F1(func_arr[0], 2);
int result_f2_macro = F2(func_arr[1], 1, 2);
std::cout << result_f1_no_macro << ", " << result_f2_no_macro << std::endl;
std::cout << result_f1_macro << ", " << result_f2_macro << std::endl;
return 0;
}
int f1(int i)
{
return i * 2;
}
int f2(int i, int j)
{
return i + j;
}
The code above produces the following output
4, 3
4, 3
The code
#include <iostream>
using namespace std;
template<int n> struct Fibo { static int x; };
template<> int Fibo<0>::x = 1;
template<> int Fibo<1>::x = 1;
template<int n> int Fibo<n>::x = Fibo<n-1>::x + Fibo<n-2>::x; //marked line
int main() {
cout << Fibo<5>::x << endl;
cout << Fibo<4>::x << endl;
cout << Fibo<3>::x << endl;
cout << Fibo<2>::x << endl;
cout << Fibo<1>::x << endl;
cout << Fibo<0>::x << endl;
return 0;
}
outputs
0
0
1
2
1
1
in VC++. (According to user M M. it compiles as expected in gcc). When the compiler gets to the marked line with n=5 it doesn't compile that same line again for n=4, but just treats Fibo<4>::x as if it were declared with
template<> int Fibo<4>::x; // x defaults to 0
Why is that? Why does it work as expected when using
template<int n> struct Fibo { enum { x = Fibo<n-1>::x + Fibo<n-2>::x }; };
template<> struct Fibo<0> { enum { x = 1 }; };
template<> struct Fibo<1> { enum { x = 1 }; };
instead, but not with a static variable? And how do you fix the first code (without enum)?
The Standard is very clear on this:
14.7.1 Implicit instantiation [temp.inst]
9 The implicit instantiation of a class template does not cause any
static data members of that class to be implicitly instantiated.
All the calls in main() to your Fibo<n>::x for n > 1, are explicit instantiations, that through the Fibonnaci recursion will implicitly instantiate Fibo<n-1> and Fibo<n-2> but not their members x. This means that at those points, the static members x will be evaluated to their default initialization of 0. For n=1 and n=0, the compiler will see the explicit initialization values of 1. So effectively, you get the following computation
Fibo<5>::x --> Fibo<4>::x + Fibo<3>::x --> 0 + 0 = 0
Fibo<4>::x --> Fibo<3>::x + Fibo<2>::x --> 0 + 0 = 0
Fibo<3>::x --> Fibo<2>::x + Fibo<1>::x --> 0 + 1 = 1
Fibo<2>::x --> Fibo<1>::x + Fibo<0>::x --> 1 + 1 = 2
Fibo<1>::x --> 1
Fibo<0>::x --> 1
You need to instantiate the static member x before evaluating the Fibonacci recursion. You can do this through a static const int or enum member x, or through a function (possibly constexpr in C++11) as shown by #Jarod42.
I'm not sure if the initialization order of the static variables of template<int n> int Fibo<n>::x = Fibo<n-1>::x + Fibo<n-2>::x; is specified...
You may write this:
template <int N> struct Fibo { int operator()() const { static int x = Fibo<N - 1>()() + Fibo<N - 2>()(); return x; } };
template <> struct Fibo<1> { int operator()() const { static int x = 1; return x; } };
template <> struct Fibo<0> { int operator()() const { static int x = 1; return x; } };
The dependencies are respected.
[Edit]
In a case where the value may be modified (according to your comment), you may use similar technique but returning reference:
template <int N> struct Fibo {
private:
int& operator()() { static int x = Fibo<N - 1>()() + Fibo<N - 2>()(); return x; }
public:
int operator()() const { return const_cast<Fibo&>(*this)(); }
// This change Fibo<0> and Fibo<1> and then update value up to Fibo<N>.
int operator(int fibo0, int fibo1) {
int n_1 = Fibo<N - 1>()(fibo1, fibo2);
(*this)() = n_1 + Fibo<N - 2>()();
}
};
template <> struct Fibo<1> {
private:
int& operator()() { static int x = 1; return x; }
public:
int operator()() const { return const_cast<Fibo&>(*this)(); }
void operator(int fibo0, int fibo1) { Fibo<0>()(fibo0); (*this)() = fibo1; }
};
template <> struct Fibo<0> {
private:
int& operator()() { static int x = 1; return x; }
public:
int operator()() const { return const_cast<Fibo&>(*this)(); }
void operator(int fibo0) { (*this)() = fibo0; }
};
The solution presented by #Jarod42 appears overly complicated to me.
Consider instead the simpler code below.
template<int N>
struct fib {
static const int val = fib<N-1>::val + fib<N-2>::val;
};
template<>
struct fib<0> { static const int val = 0;};
template<>
struct fib<1> { static const int val = 1;};
int main() {
std::cout << fib<45>::val << "\n";
return 0;
}
Here is my code.
#include <map>
#include <string>
#include <algorithm>
class maptest {
public:
int doubler(int val) { return val * 2; }
int halver(int val) { return val / 2; }
int negativer(int val) { return val > 0 ? -val : val; }
};
int main() {
const char* const ID[] = {"doubler", "halver", "negativer" };
int ID_SIZE = sizeof(ID) / sizeof(*ID);
//signature of maths functions
typedef int (maptest::*mathfunc)(int);
mathfunc mfuncs[] = { &maptest::doubler, &maptest::halver, &maptest::negativer};
std::map<std::string, mathfunc> mathmap;
for(int i = 0; i < ID_SIZE; ++i) {
mathmap.insert(std::make_pair(ID[i], mfuncs[i]));
}
//C2064: term does not evaluate to a function taking 1 argument
int result = *mathmap["doubler"](3);
return 0;
}
I think this would work if there was no parameter to be passed to the functions. But how do I pass a parameter in this way?
Your mathfuncs are member functions, so you need an object on which to invoke them:
maptest mt;
int result = (mt.*(mathmap["doubler"]))(3);
Alternatively, you could make your member functions static:
class maptest {
public:
static int doubler(int val) { return val * 2; }
static int halver(int val) { return val / 2; }
static int negativer(int val) { return val > 0 ? -val : val; }
};
And then define mathfunc accordingly:
typedef int (*mathfunc)(int);
And this would allow you to invoke them the way you are invoking them in your original post:
typedef int (*mathfunc)(int);
Notice, that a way to make this design more flexible is to make use of std::function, which would allow you to pass any type of callable object. For instance:
typedef std::function<int(int)> mathfunc;
mathfunc mfuncs[] = {
&maptest::doubler,
&maptest::halver,
&maptest::negativer,
[] (int i) { return i * 2; } // <== A LAMBDA...
};
You are invoking non static member function.
do the following.
maptest t;
int (maptest::*tptr) (int) = mathmap["doubler"];
int result = (t.*tptr)(2);
Hope this helps.