By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
434,573 Members | 903 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 434,573 IT Pros & Developers. It's quick & easy.

template function as function parameter

P: n/a
rg
Hi all,

I was wondering if anyone had dealt with a similar problem. I need to use a
template function as the parameter for a particular function (also template
function).
The program compiles into an object file but then at the final stage it says
that it can't find template function. The platform is WindowsXP Pro, MSCV++
..Net.

More specifically what I want to do is write an atl algorithm that will also
accept another algorithm as a function parameter. This is inteface of the
outer algorithm:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t loop = std::distance( begin, end) / slide;
for ( std::size_t x = 0; x < loop; ++x, ++outbegin, begin =
std::advance( begin, size) ) // only do complete cycles, not parts
*outbegin = alg( begin, std::advance( begin, size) );
}

What I want to do with is perform some calculations on range on a sliding
basis. For example, if I have a array of 1000 values, I may want to
calculate the average of every 100 of those values.

Any help would be appreciated. Many Thanks in advance.

RG
Jul 22 '05 #1
Share this Question
Share on Google+
10 Replies


P: n/a

"rg" <rg****@hotmail.com> wrote in message
news:ce**********@news.freedom2surf.net...
Hi all,

I was wondering if anyone had dealt with a similar problem. I need to use a template function as the parameter for a particular function (also template function).
The program compiles into an object file but then at the final stage it says that it can't find template function. The platform is WindowsXP Pro, MSCV++ .Net.
Are you falling into the trap where you place template code in the
implementation (.cpp) file instead of placing all of it in the header? See
the FAQ
(http://www.parashift.com/c++-faq-lit...templates.html) for
info about linker errors with templates.
More specifically what I want to do is write an atl algorithm that will also accept another algorithm as a function parameter. This is inteface of the
outer algorithm:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t loop = std::distance( begin, end) / slide;
for ( std::size_t x = 0; x < loop; ++x, ++outbegin, begin =
std::advance( begin, size) ) // only do complete cycles, not parts
*outbegin = alg( begin, std::advance( begin, size) );
}


This may have weird behavior on some inputs. Consider the behavior if the
distance is 1 and the slide is 2, where nothing is performed. Also, you
could accidentally run off the end of the container with the call to
advance(). Maybe something like this would be safer:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t dist = std::distance( begin, end );
for ( std::size_t x = 0; x < dist; x += slide, ++outbegin )
// only do complete cycles, not parts
iterator tmp = std::advance( begin, std::min(slide, dist-x) );
*outbegin = alg( begin, tmp );
begin = tmp;
}

The code above is untested.

--
David Hilsee
Jul 22 '05 #2

P: n/a
"David Hilsee" <da*************@yahoo.com> wrote in message
news:-8********************@comcast.com...
This may have weird behavior on some inputs. Consider the behavior if the
distance is 1 and the slide is 2, where nothing is performed. Also, you
could accidentally run off the end of the container with the call to
advance(). Maybe something like this would be safer:


Sorry, that comment about the end of the container, AFAICT, does not apply
to your code. It applies to the code that I provided if the call to
std::min is removed.

--
David Hilsee
Jul 22 '05 #3

P: n/a
"David Hilsee" <da*************@yahoo.com> wrote in message
news:-8********************@comcast.com...
template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t dist = std::distance( begin, end );
for ( std::size_t x = 0; x < dist; x += slide, ++outbegin )
// only do complete cycles, not parts
iterator tmp = std::advance( begin, std::min(slide, dist-x) );
*outbegin = alg( begin, tmp );
begin = tmp;
}


And for my final response to myself, I would like to point out that I didn't
even try to understand the comment that I cut-and-pasted from the original
code and made the code I posted almost completely irrelevant. *smacks
forehead*

--
David Hilsee
Jul 22 '05 #4

P: n/a
On Tue, 3 Aug 2004 23:28:34 +0100, rg <rg****@hotmail.com> wrote:
Hi all,

I was wondering if anyone had dealt with a similar problem. I need to
use a
template function as the parameter for a particular function (also
template
function).
The program compiles into an object file but then at the final stage it
says
that it can't find template function. The platform is WindowsXP Pro,
MSCV++
.Net.

More specifically what I want to do is write an atl algorithm that will
also
accept another algorithm as a function parameter. This is inteface of the
outer algorithm:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t loop = std::distance( begin, end) / slide;
for ( std::size_t x = 0; x < loop; ++x, ++outbegin, begin =
std::advance( begin, size) ) // only do complete cycles, not parts
*outbegin = alg( begin, std::advance( begin, size) );
}

What I want to do with is perform some calculations on range on a sliding
basis. For example, if I have a array of 1000 values, I may want to
calculate the average of every 100 of those values.

Any help would be appreciated. Many Thanks in advance.

RG


I think I'd want to see the code that calls transform_slide.

Maybe I've having a bad day but I can't see how a template function (or
any sort of function) could be a suitable argument for class Arg, surely
you need a non-type template argument? Something like

template <class I, class OI, class T>
void transform_slide(I begin, I end, OI outbegin, size_t slide, T
(*Alg)(I, size_t))
{
}

john
Jul 22 '05 #5

P: n/a
On Wed, 04 Aug 2004 06:50:46 +0100, John Harrison
<jo*************@hotmail.com> wrote:

Maybe I've having a bad day but I can't see how a template function (or
any sort of function) could be a suitable argument for class Arg, surely
you need a non-type template argument?


Yeah I've having a bad day, please ignore.

john
Jul 22 '05 #6

P: n/a
rg
Hi,
Thanks for your reply.
The algorithm that I am talking about is indeed in the header (.hpp) file. I
think the problem is that the template function is not actually instantiated
until it is used so when I send a pointer to it, there is nothing to point
at. I'm wondering if there's anything to deal with that. I tried:

using alg< vector<int>::iterator >;

but that didn't work.

Many thanks

RG

"David Hilsee" <da*************@yahoo.com> wrote in message
news:-8********************@comcast.com...

"rg" <rg****@hotmail.com> wrote in message
news:ce**********@news.freedom2surf.net...
Hi all,

I was wondering if anyone had dealt with a similar problem. I need to use
a
template function as the parameter for a particular function (also template
function).
The program compiles into an object file but then at the final stage it

says
that it can't find template function. The platform is WindowsXP Pro,

MSCV++
.Net.


Are you falling into the trap where you place template code in the
implementation (.cpp) file instead of placing all of it in the header?

See the FAQ
(http://www.parashift.com/c++-faq-lit...templates.html) for
info about linker errors with templates.
More specifically what I want to do is write an atl algorithm that will

also
accept another algorithm as a function parameter. This is inteface of

the outer algorithm:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t loop = std::distance( begin, end) / slide;
for ( std::size_t x = 0; x < loop; ++x, ++outbegin, begin =
std::advance( begin, size) ) // only do complete cycles, not parts
*outbegin = alg( begin, std::advance( begin, size) );
}


This may have weird behavior on some inputs. Consider the behavior if the
distance is 1 and the slide is 2, where nothing is performed. Also, you
could accidentally run off the end of the container with the call to
advance(). Maybe something like this would be safer:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t dist = std::distance( begin, end );
for ( std::size_t x = 0; x < dist; x += slide, ++outbegin )
// only do complete cycles, not parts
iterator tmp = std::advance( begin, std::min(slide, dist-x) );
*outbegin = alg( begin, tmp );
begin = tmp;
}

The code above is untested.

--
David Hilsee

Jul 22 '05 #7

P: n/a
rg
Hi,

Thank you for your reply.

I was going to use it to calculate the rms power for each second in a sound
sample. Currently I'm using a rms_slide algorithm but I wanted to make a
more generic algorithm that can be used for sliding against any custom
algorithm.

Many Thanks

RG

"John Harrison" <jo*************@hotmail.com> wrote in message
news:opsb606wa5212331@andronicus...
On Tue, 3 Aug 2004 23:28:34 +0100, rg <rg****@hotmail.com> wrote:
Hi all,

I was wondering if anyone had dealt with a similar problem. I need to
use a
template function as the parameter for a particular function (also
template
function).
The program compiles into an object file but then at the final stage it
says
that it can't find template function. The platform is WindowsXP Pro,
MSCV++
.Net.

More specifically what I want to do is write an atl algorithm that will
also
accept another algorithm as a function parameter. This is inteface of the outer algorithm:

template <class iterator, class outiterator, class Alg>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin, std::size_t slide, Alg alg)
{
std::size_t loop = std::distance( begin, end) / slide;
for ( std::size_t x = 0; x < loop; ++x, ++outbegin, begin =
std::advance( begin, size) ) // only do complete cycles, not parts
*outbegin = alg( begin, std::advance( begin, size) );
}

What I want to do with is perform some calculations on range on a sliding basis. For example, if I have a array of 1000 values, I may want to
calculate the average of every 100 of those values.

Any help would be appreciated. Many Thanks in advance.

RG

I think I'd want to see the code that calls transform_slide.

Maybe I've having a bad day but I can't see how a template function (or
any sort of function) could be a suitable argument for class Arg, surely

you need a non-type template argument? Something like

template <class I, class OI, class T>
void transform_slide(I begin, I end, OI outbegin, size_t slide, T
(*Alg)(I, size_t))
{
}

john

Jul 22 '05 #8

P: n/a
"rg" <rg****@hotmail.com> wrote in message
news:ce**********@news.freedom2surf.net...

I think you might have overlooked John's request:
I think I'd want to see the code that calls transform_slide.


Also, it might be good to know exactly where the caller's code, and any code
it references, is located (defined in "blah.cpp"/declared in "blah.hpp").

--
David Hilsee
Jul 22 '05 #9

P: n/a
rg
Hi,

Sorry for not having replied earlier, been extremely busy. Here is the code:

file stats.hpp
{
#insert...
.....

template <class iterator>
double rms(iterator begin, iterator end) // calculates the Root Mean
Square Power for some range of values
{
return std::sqrt(
std::accumulate(
begin, end, 0.0, boost::bind<double>(
std::plus<double>(), _1,
boost::bind(std::pow, _2, 2)
)
) / std::distance(begin, end)
);
}

template <class iterator, class outiterator>
void rms_slide ( iterator begin, iterator end, outiterator outbegin,
std::size_t slide) // calculates RMS over a sliding frame
{
std::size_t loop = std::distance( begin, end) / slide;
end = begin + slide;
for (
std::size_t x = 0;
x < loop;
++x, ++outbegin, std::advance( begin, slide), std::advance (
end, slide)
) // only do complete cycles, not parts
*outbegin = rms( begin, end );
}

} // end stats.hpp
file main.cpp
{
short * wav = new short[SIZE]; //array contain audio data
std::vector<int> power; // to hold rms power information over time

rms_slide( wav, wav + SIZE, std::back_inserter(power), SLIDE_SIZE );
// calculate RMS power for frames of size SLIDE_SIZE

delete[] wav;
}// end main.cpp
When I did this, I wondered whether I could develop a more generic version
of the slide algorithm which I described in my earlier post. Instead of
calling rms_slide, I would call:

transform_slide (
wav,
wav + SIZE,
std::back_inserter(power),
SLIDE_SIZE,
rms
);

and tell it to apply the rms algorithm over the sliding frame and insert the
value into the output iterator.

Hope it makes sense. Many Thanks for your help.

RG

"David Hilsee" <da*************@yahoo.com> wrote in message
news:dv********************@comcast.com...
"rg" <rg****@hotmail.com> wrote in message
news:ce**********@news.freedom2surf.net...

I think you might have overlooked John's request:
I think I'd want to see the code that calls transform_slide.

Also, it might be good to know exactly where the caller's code, and any

code it references, is located (defined in "blah.cpp"/declared in "blah.hpp").

--
David Hilsee

Jul 22 '05 #10

P: n/a
"rg" <rg****@hotmail.com> wrote in message
news:cf**********@news.freedom2surf.net...
Hi,

Sorry for not having replied earlier, been extremely busy. Here is the code:
file stats.hpp
{
#insert...
....

template <class iterator>
double rms(iterator begin, iterator end) // calculates the Root Mean Square Power for some range of values
{
return std::sqrt(
std::accumulate(
begin, end, 0.0, boost::bind<double>(
std::plus<double>(), _1,
boost::bind(std::pow, _2, 2)
)
) / std::distance(begin, end)
);
}

template <class iterator, class outiterator>
void rms_slide ( iterator begin, iterator end, outiterator outbegin,
std::size_t slide) // calculates RMS over a sliding frame
{
std::size_t loop = std::distance( begin, end) / slide;
end = begin + slide;
for (
std::size_t x = 0;
x < loop;
++x, ++outbegin, std::advance( begin, slide), std::advance (
end, slide)
) // only do complete cycles, not parts
*outbegin = rms( begin, end );
}

} // end stats.hpp
file main.cpp
{
short * wav = new short[SIZE]; //array contain audio data
std::vector<int> power; // to hold rms power information over time

rms_slide( wav, wav + SIZE, std::back_inserter(power), SLIDE_SIZE ); // calculate RMS power for frames of size SLIDE_SIZE

delete[] wav;
}// end main.cpp
When I did this, I wondered whether I could develop a more generic version
of the slide algorithm which I described in my earlier post. Instead of
calling rms_slide, I would call:

transform_slide (
wav,
wav + SIZE,
std::back_inserter(power),
SLIDE_SIZE,
rms
);

and tell it to apply the rms algorithm over the sliding frame and insert the value into the output iterator.

Hope it makes sense. Many Thanks for your help.


How about:

template <class iterator, class outiterator, class fun>
void transform_slide ( iterator begin, iterator end, outiterator
outbegin,
std::size_t slide, fun f )
{
std::cout << "A" << std::endl;
std::size_t loop = std::distance( begin, end ) / slide;
end = begin;
std::advance( end, slide );
for (
std::size_t x = 0;
x < loop;
++x, ++outbegin, begin = end, std::advance(end,slide)
)

*outbegin = f( begin, end );
}

template <class it>
double rms(it beg, it end) {return 0;}

// Allows the compiler to figure out what type the iterator
// should be
struct rms_wrapper {
template <class it>
double operator()(it beg, it end){
return rms(beg,end);
}
};

int main() {
std::vector<double> v;

transform_slide(v.begin(),v.end(),v.begin(),1,rms< std::vector<double>::itera
tor>);
transform_slide(v.begin(),v.end(),v.begin(),1,rms_ wrapper());
}

But didn't you say something about a linker error? Can't find the function,
or something to that effect?

--
David Hilsee
Jul 22 '05 #11

This discussion thread is closed

Replies have been disabled for this discussion.