473,382 Members | 1,302 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,382 software developers and data experts.

template for function pointer

Hello everyone,
here is my program:

///////////////////////////////
#include <iostream>
using namespace std;

void multi(double* arrayPtr, int len){
for(int i=0; i<len; i++)
*(arrayPtr+i)*=2;
}
typedef void (*p2f) (double* a, int b);
//////////////////////////////
template <class T>
class bf{
private:
int type;
T var;
public:
bf(int i, T value){ type=i; var=value;}
void eval(double* dPtr, int len);
};

template <class T>
void bf<T>::eval(double* dPtr, int len){
switch(type){
case 0:
for(int i=0; i<len; i++)
*(dPtr+i)=var;
break;
case 1:
for(int i=0; i<len; i++)
*(dPtr+i)=*(var+i);
break;
case 2:
var(dPtr, len);
break;
}
}

void main(){
double a=0.0;
bf<double> a1(0,a);

double b[3]={0.0, 1.0, 2.0};
bf<double*> a2(1,b);

bf<p2f> a3(2,multi);

double temp[3]={5.0, 5.0, 5.0};
a1.eval(temp,3);
for(int i=0;i<3;i++)
cout<<temp[i]<<endl;
}

I have a bf class with a member variable "var" whose type is defined as
a template. In bf's constructor, I use (int type) to record what type
var is defined.
The main purpose of bf is to retrieve a double array, then modified it
using the var member.
By different types of var, it does different modifies to the input
array.

There are 3 conditions:
If var is a double( it can be known from "type" variable), it fill the
incoming array with the double value.
If var is a double array, it copies its value one by one into the
incoming array.
If var is a function pointer, it takes the incoming array as the
argument.

There's no problem untill I call bf::eval() in main();
It seems like that if var is a double then the code "var(dPtr, len);"
is wrong. In fact, it is wrong. But that is in case 2. Whenever the var
is not a function pointer, it will never go into case 2 in the switch
in eval();
The familiar situation also happens when the var is set to a function
pointer. The error was found in case 0, in which var is treated as a
double.

I just wanna control the branch call by myself.
Is there any solution?
Thanks

Jul 22 '05 #1
4 2220

<fi******@yahoo.com.tw> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
Hello everyone,
here is my program:

///////////////////////////////
#include <iostream>
using namespace std;

void multi(double* arrayPtr, int len){
for(int i=0; i<len; i++)
*(arrayPtr+i)*=2;
}
typedef void (*p2f) (double* a, int b);
//////////////////////////////
template <class T>
class bf{
private:
int type;
T var;
public:
bf(int i, T value){ type=i; var=value;}
void eval(double* dPtr, int len);
};

Generally, you use a template when you want to apply the same code
structure to different types. Your problem here is that you are trying
to apply different code depending on the type which fails because you
cannot provide a T that has all the necessary properties.
template <class T>
void bf<T>::eval(double* dPtr, int len){
switch(type){
case 0:
for(int i=0; i<len; i++)
*(dPtr+i)=var;
In order for this line to compile, it must be possible to convert T to a
double.
break;
case 1:
for(int i=0; i<len; i++)
*(dPtr+i)=*(var+i);
In order for this line to compile, it must be possible to convert T to a
double*.
break;
case 2:
var(dPtr, len);
In order for this line to compile,
T must have a constructor that takes a double* and an int.
break;
}
}

So, if you want the preceding method to compile, you need to use a T for
which the following statements are all valid:

T t1;
double d = t1;
double* p = t1;
T t2(p, 1);
void main(){
double a=0.0;
bf<double> a1(0,a);

double b[3]={0.0, 1.0, 2.0};
bf<double*> a2(1,b);

bf<p2f> a3(2,multi);

double temp[3]={5.0, 5.0, 5.0};
a1.eval(temp,3);
for(int i=0;i<3;i++)
cout<<temp[i]<<endl;
}

I have a bf class with a member variable "var" whose type is defined as a template. In bf's constructor, I use (int type) to record what type
var is defined.
The main purpose of bf is to retrieve a double array, then modified it
using the var member.
By different types of var, it does different modifies to the input
array.

There are 3 conditions:
If var is a double( it can be known from "type" variable), it fill the
incoming array with the double value.
If var is a double array, it copies its value one by one into the
incoming array.
If var is a function pointer, it takes the incoming array as the
argument.

There's no problem untill I call bf::eval() in main();
It seems like that if var is a double then the code "var(dPtr, len);"
is wrong. In fact, it is wrong. But that is in case 2. Whenever the var is not a function pointer, it will never go into case 2 in the switch
in eval();
The familiar situation also happens when the var is set to a function
pointer. The error was found in case 0, in which var is treated as a
double.

I just wanna control the branch call by myself.
Is there any solution?
Thanks


I will ignore other obvious, dangerous errors in your code since I think
you are really misguided in trying to do what you are doing.

Some advice:

First read some more about C++ and object-oriented programming. You are
trying to treat numerical, pointer and function pointer types like they
are the same thing when they are very different creatures.

Read much more about templates. In particular, take a look at STL type
requirements, which specify the properties a type must have in order to
be used with a particular template. A vector, for instance, requires
that T be 'Assignable' meaning that you can write:
T a;
T b = a;

Perhaps if you state what higher level problem you are trying to solve
you will get some useful advice. In the meantime, remember that
templates will only work with types that have something in common.

Merry New Year
Tom
Jul 22 '05 #2
Hi Thomas,

The problem you are seeing is that the compiler is trying to compile all
three branches of the case statement *for each type of the template
parameter* and all those branches are not valid of all the template
parameters you are using.

I am going to throw some code at you that perhaps solves you requirements in
different way. Have a look at it. It probably introduces some new concepts
but these concepts lend themselve more correctly to solving the type of
problem you are trying to solve.

///////////////////////////////////////

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

using namespace std;

double doubleArray[] = { 1.0, 2.0, 3.0 };
const size_t sz = 3;
double doubleArrayTwo[] = { 5.0, 6.0, 7.0 };
const size_t sz2 = 3;

double func(const double elem)
{
return elem*2;
}
int main()
{
vector<double> myDoubleVec(&doubleArray[0],
&doubleArray[3]);

// case 1
double val = 5;

fill(myDoubleVec.begin(),
myDoubleVec.end(),
5);

// print the result
copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

// case 2

copy(&doubleArrayTwo[0],
&doubleArrayTwo[sz2],
myDoubleVec.begin());

// print the result
copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

// case 3
transform(myDoubleVec.begin(),
myDoubleVec.end(),
myDoubleVec. begin(),
func);

copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

return 0;
}
///////////////////////////////////////////////////////////////////////
Let me know how it goes.

Regards,
Bruce
<fi******@yahoo.com.tw> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
Hello everyone,
here is my program:

///////////////////////////////
#include <iostream>
using namespace std;

void multi(double* arrayPtr, int len){
for(int i=0; i<len; i++)
*(arrayPtr+i)*=2;
}
typedef void (*p2f) (double* a, int b);
//////////////////////////////
template <class T>
class bf{
private:
int type;
T var;
public:
bf(int i, T value){ type=i; var=value;}
void eval(double* dPtr, int len);
};

template <class T>
void bf<T>::eval(double* dPtr, int len){
switch(type){
case 0:
for(int i=0; i<len; i++)
*(dPtr+i)=var;
break;
case 1:
for(int i=0; i<len; i++)
*(dPtr+i)=*(var+i);
break;
case 2:
var(dPtr, len);
break;
}
}

void main(){
double a=0.0;
bf<double> a1(0,a);

double b[3]={0.0, 1.0, 2.0};
bf<double*> a2(1,b);

bf<p2f> a3(2,multi);

double temp[3]={5.0, 5.0, 5.0};
a1.eval(temp,3);
for(int i=0;i<3;i++)
cout<<temp[i]<<endl;
}

I have a bf class with a member variable "var" whose type is defined as
a template. In bf's constructor, I use (int type) to record what type
var is defined.
The main purpose of bf is to retrieve a double array, then modified it
using the var member.
By different types of var, it does different modifies to the input
array.

There are 3 conditions:
If var is a double( it can be known from "type" variable), it fill the
incoming array with the double value.
If var is a double array, it copies its value one by one into the
incoming array.
If var is a function pointer, it takes the incoming array as the
argument.

There's no problem untill I call bf::eval() in main();
It seems like that if var is a double then the code "var(dPtr, len);"
is wrong. In fact, it is wrong. But that is in case 2. Whenever the var
is not a function pointer, it will never go into case 2 in the switch
in eval();
The familiar situation also happens when the var is set to a function
pointer. The error was found in case 0, in which var is treated as a
double.

I just wanna control the branch call by myself.
Is there any solution?
Thanks


Jul 22 '05 #3
Sorry, my response was not to Thomas but to the original poster.
"Bruce Trask" <b_*****@yahoo.com> wrote in message
news:AuKBd.18469$152.17240@trndny01...
Hi Thomas,

The problem you are seeing is that the compiler is trying to compile all
three branches of the case statement *for each type of the template
parameter* and all those branches are not valid of all the template
parameters you are using.

I am going to throw some code at you that perhaps solves you requirements in different way. Have a look at it. It probably introduces some new concepts but these concepts lend themselve more correctly to solving the type of
problem you are trying to solve.

///////////////////////////////////////

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

using namespace std;

double doubleArray[] = { 1.0, 2.0, 3.0 };
const size_t sz = 3;
double doubleArrayTwo[] = { 5.0, 6.0, 7.0 };
const size_t sz2 = 3;

double func(const double elem)
{
return elem*2;
}
int main()
{
vector<double> myDoubleVec(&doubleArray[0],
&doubleArray[3]);

// case 1
double val = 5;

fill(myDoubleVec.begin(),
myDoubleVec.end(),
5);

// print the result
copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

// case 2

copy(&doubleArrayTwo[0],
&doubleArrayTwo[sz2],
myDoubleVec.begin());

// print the result
copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

// case 3
transform(myDoubleVec.begin(),
myDoubleVec.end(),
myDoubleVec. begin(),
func);

copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

return 0;
}
///////////////////////////////////////////////////////////////////////
Let me know how it goes.

Regards,
Bruce
<fi******@yahoo.com.tw> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
Hello everyone,
here is my program:

///////////////////////////////
#include <iostream>
using namespace std;

void multi(double* arrayPtr, int len){
for(int i=0; i<len; i++)
*(arrayPtr+i)*=2;
}
typedef void (*p2f) (double* a, int b);
//////////////////////////////
template <class T>
class bf{
private:
int type;
T var;
public:
bf(int i, T value){ type=i; var=value;}
void eval(double* dPtr, int len);
};

template <class T>
void bf<T>::eval(double* dPtr, int len){
switch(type){
case 0:
for(int i=0; i<len; i++)
*(dPtr+i)=var;
break;
case 1:
for(int i=0; i<len; i++)
*(dPtr+i)=*(var+i);
break;
case 2:
var(dPtr, len);
break;
}
}

void main(){
double a=0.0;
bf<double> a1(0,a);

double b[3]={0.0, 1.0, 2.0};
bf<double*> a2(1,b);

bf<p2f> a3(2,multi);

double temp[3]={5.0, 5.0, 5.0};
a1.eval(temp,3);
for(int i=0;i<3;i++)
cout<<temp[i]<<endl;
}

I have a bf class with a member variable "var" whose type is defined as
a template. In bf's constructor, I use (int type) to record what type
var is defined.
The main purpose of bf is to retrieve a double array, then modified it
using the var member.
By different types of var, it does different modifies to the input
array.

There are 3 conditions:
If var is a double( it can be known from "type" variable), it fill the
incoming array with the double value.
If var is a double array, it copies its value one by one into the
incoming array.
If var is a function pointer, it takes the incoming array as the
argument.

There's no problem untill I call bf::eval() in main();
It seems like that if var is a double then the code "var(dPtr, len);"
is wrong. In fact, it is wrong. But that is in case 2. Whenever the var
is not a function pointer, it will never go into case 2 in the switch
in eval();
The familiar situation also happens when the var is set to a function
pointer. The error was found in case 0, in which var is treated as a
double.

I just wanna control the branch call by myself.
Is there any solution?
Thanks


Jul 22 '05 #4
Aside from taking a different approach with the STL, you had a question as
to how to make the compiler avoid some branches in the code. The answer to
that would be to provide template specializations for the eval member
function. This gives you what amounts to a compile time switch. See the
code below to see how this works. It has the added benefit of failing at
link time if anyone uses a type that you have not provided a specialization
for.

#include <iostream>
using namespace std;

void multi(double* arrayPtr, int len){
for(int i=0; i<len; i++)
*(arrayPtr+i)*=2;
}
typedef void (*p2f) (double* a, int b);
//////////////////////////////
template <class T>
class bf{
private:
int type;
T var;
public:
bf(int i, T value){ type=i; var=value;}
void eval(double* dPtr, int len);
};

template <>
void bf<double>::eval(double* dPtr, int len){
cout << "1" << endl;
for(int i=0; i<len; i++)
*(dPtr+i)=var;
}

template <>
void bf<double*>::eval(double* dPtr, int len){
cout << "2" << endl;
for(int i=0; i<len; i++)
*(dPtr+i)=*(var+i);
}

template <>
void bf<p2f>::eval(double* dPtr, int len){
cout << "3" << endl;
var(dPtr, len);
}

int main(){
double a=0.0;
bf<double> a1(0,a);

double b[3]={0.0, 1.0, 2.0};
bf<double*> a2(1,b);

bf<p2f> a3(2,multi);

double temp[3]={5.0, 5.0, 5.0};
cout << "calling eval" << endl;
a1.eval(temp,3);
for(int i=0;i<3;i++)
cout<<temp[i]<<endl;
}

Hope that helps,
Bruce

"Bruce Trask" <b_*****@yahoo.com> wrote in message
news:6wKBd.10427$sh5.8053@trndny08...
Sorry, my response was not to Thomas but to the original poster.
"Bruce Trask" <b_*****@yahoo.com> wrote in message
news:AuKBd.18469$152.17240@trndny01...
Hi Thomas,

The problem you are seeing is that the compiler is trying to compile all
three branches of the case statement *for each type of the template
parameter* and all those branches are not valid of all the template
parameters you are using.

I am going to throw some code at you that perhaps solves you
requirements in
different way. Have a look at it. It probably introduces some new

concepts
but these concepts lend themselve more correctly to solving the type of
problem you are trying to solve.

///////////////////////////////////////

#include <vector>
#include <algorithm>
#include <iterator>
#include <iostream>

using namespace std;

double doubleArray[] = { 1.0, 2.0, 3.0 };
const size_t sz = 3;
double doubleArrayTwo[] = { 5.0, 6.0, 7.0 };
const size_t sz2 = 3;

double func(const double elem)
{
return elem*2;
}
int main()
{
vector<double> myDoubleVec(&doubleArray[0],
&doubleArray[3]);

// case 1
double val = 5;

fill(myDoubleVec.begin(),
myDoubleVec.end(),
5);

// print the result
copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

// case 2

copy(&doubleArrayTwo[0],
&doubleArrayTwo[sz2],
myDoubleVec.begin());

// print the result
copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

// case 3
transform(myDoubleVec.begin(),
myDoubleVec.end(),
myDoubleVec. begin(),
func);

copy(myDoubleVec.begin(),
myDoubleVec.end(),
ostream_iterator<double>(cout,"\n"));

return 0;
}
///////////////////////////////////////////////////////////////////////
Let me know how it goes.

Regards,
Bruce
<fi******@yahoo.com.tw> wrote in message
news:11*********************@z14g2000cwz.googlegro ups.com...
Hello everyone,
here is my program:

///////////////////////////////
#include <iostream>
using namespace std;

void multi(double* arrayPtr, int len){
for(int i=0; i<len; i++)
*(arrayPtr+i)*=2;
}
typedef void (*p2f) (double* a, int b);
//////////////////////////////
template <class T>
class bf{
private:
int type;
T var;
public:
bf(int i, T value){ type=i; var=value;}
void eval(double* dPtr, int len);
};

template <class T>
void bf<T>::eval(double* dPtr, int len){
switch(type){
case 0:
for(int i=0; i<len; i++)
*(dPtr+i)=var;
break;
case 1:
for(int i=0; i<len; i++)
*(dPtr+i)=*(var+i);
break;
case 2:
var(dPtr, len);
break;
}
}

void main(){
double a=0.0;
bf<double> a1(0,a);

double b[3]={0.0, 1.0, 2.0};
bf<double*> a2(1,b);

bf<p2f> a3(2,multi);

double temp[3]={5.0, 5.0, 5.0};
a1.eval(temp,3);
for(int i=0;i<3;i++)
cout<<temp[i]<<endl;
}

I have a bf class with a member variable "var" whose type is defined as a template. In bf's constructor, I use (int type) to record what type
var is defined.
The main purpose of bf is to retrieve a double array, then modified it
using the var member.
By different types of var, it does different modifies to the input
array.

There are 3 conditions:
If var is a double( it can be known from "type" variable), it fill the
incoming array with the double value.
If var is a double array, it copies its value one by one into the
incoming array.
If var is a function pointer, it takes the incoming array as the
argument.

There's no problem untill I call bf::eval() in main();
It seems like that if var is a double then the code "var(dPtr, len);"
is wrong. In fact, it is wrong. But that is in case 2. Whenever the var is not a function pointer, it will never go into case 2 in the switch
in eval();
The familiar situation also happens when the var is set to a function
pointer. The error was found in case 0, in which var is treated as a
double.

I just wanna control the branch call by myself.
Is there any solution?
Thanks



Jul 22 '05 #5

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Surya Kiran | last post by:
Hi all, I've written a function template. say template <class T> fn (T var) { ... } Is there any way, from within the function, can we check what type of argument we've passed on to the...
5
by: Suzanne Vogel | last post by:
Is it possible to store a pointer to a template function? eg, template<class T> fooFunc() {...} fptr = fooFunc; // <-- I couldn't find any info here, not even in the forums:...
4
by: Carsten Spieß | last post by:
Hello all, i have a problem with a template constructor I reduced my code to the following (compiled with gcc 2.7.2) to show my problem: // a base class class Base{}; // two derived...
13
by: Gurikar | last post by:
Hello, Can anyone tell me whats wrong in this? // template function template<class T> inline void test(T* ptr) { cout<<"Pointer is"<<ptr<<endl; ptr = NULL; cout<<"Pointer is"<<ptr<<endl;
4
by: Vijai Kalyan | last post by:
I was decomposing a task into different policies. Essentially, there is a general option obtained from a server and user options obtained from configuration variables. The two options are...
5
by: StephQ | last post by:
This is from a thread that I posted on another forum some days ago. I didn't get any response, so I'm proposing it in this ng in hope of better luck :) The standard explanation is that pointer...
3
by: .rhavin grobert | last post by:
guess you have the following: _________________________________________________ template <class T> class CQVector { public: // find an element, returns index or -1 if none is found int...
6
by: Gaijinco | last post by:
I'm trying to do a template class Node. My node.hpp is: #ifndef _NODE_HPP_ #define _NODE_HPP_ namespace com { namespace mnya { namespace carlos { template <typename T>
2
by: Clyde | last post by:
Hi, what i'm trying to do is: /////////////// Code Start template <class TType, int* p = 0> class Template { public:
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: ryjfgjl | last post by:
In our work, we often receive Excel tables with data in the same format. If we want to analyze these data, it can be difficult to analyze them because the data is spread across multiple Excel files...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.