template function as function parameter

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • rg

    template function as function parameter

    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


  • David Hilsee

    #2
    Re: template function as function parameter


    "rg" <rg1117@hotmail .com> wrote in message
    news:cep3ld$f85 $1@news.freedom 2surf.net...[color=blue]
    > Hi all,
    >
    > I was wondering if anyone had dealt with a similar problem. I need to use[/color]
    a[color=blue]
    > template function as the parameter for a particular function (also[/color]
    template[color=blue]
    > function).
    > The program compiles into an object file but then at the final stage it[/color]
    says[color=blue]
    > that it can't find template function. The platform is WindowsXP Pro,[/color]
    MSCV++[color=blue]
    > .Net.[/color]

    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.
    [color=blue]
    > More specifically what I want to do is write an atl algorithm that will[/color]
    also[color=blue]
    > 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) );
    > }[/color]

    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


    Comment

    • David Hilsee

      #3
      Re: template function as function parameter

      "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message
      news:-8ydnZJla9M6tY3c RVn-uA@comcast.com. ..
      [color=blue]
      > 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:[/color]

      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


      Comment

      • David Hilsee

        #4
        Re: template function as function parameter

        "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message
        news:-8ydnZJla9M6tY3c RVn-uA@comcast.com. ..
        [color=blue]
        > 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;
        > }[/color]

        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


        Comment

        • John Harrison

          #5
          Re: template function as function parameter

          On Tue, 3 Aug 2004 23:28:34 +0100, rg <rg1117@hotmail .com> wrote:
          [color=blue]
          > 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
          >[/color]

          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

          Comment

          • John Harrison

            #6
            Re: template function as function parameter

            On Wed, 04 Aug 2004 06:50:46 +0100, John Harrison
            <john_andronicu s@hotmail.com> wrote:
            [color=blue]
            >
            > 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?[/color]

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

            john

            Comment

            • rg

              #7
              Re: template function as function parameter

              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>::it erator >;

              but that didn't work.

              Many thanks

              RG

              "David Hilsee" <davidhilseenew s@yahoo.com> wrote in message
              news:-8ydnZJla9M6tY3c RVn-uA@comcast.com. ..[color=blue]
              >
              > "rg" <rg1117@hotmail .com> wrote in message
              > news:cep3ld$f85 $1@news.freedom 2surf.net...[color=green]
              > > Hi all,
              > >
              > > I was wondering if anyone had dealt with a similar problem. I need to[/color][/color]
              use[color=blue]
              > a[color=green]
              > > template function as the parameter for a particular function (also[/color]
              > template[color=green]
              > > function).
              > > The program compiles into an object file but then at the final stage it[/color]
              > says[color=green]
              > > that it can't find template function. The platform is WindowsXP Pro,[/color]
              > MSCV++[color=green]
              > > .Net.[/color]
              >
              > 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?[/color]
              See[color=blue]
              > the FAQ
              > (http://www.parashift.com/c++-faq-lit...templates.html) for
              > info about linker errors with templates.
              >[color=green]
              > > More specifically what I want to do is write an atl algorithm that will[/color]
              > also[color=green]
              > > accept another algorithm as a function parameter. This is inteface of[/color][/color]
              the[color=blue][color=green]
              > > 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) );
              > > }[/color]
              >
              > 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
              >
              >[/color]


              Comment

              • rg

                #8
                Re: template function as function parameter

                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" <john_andronicu s@hotmail.com> wrote in message
                news:opsb606wa5 212331@andronic us...[color=blue]
                > On Tue, 3 Aug 2004 23:28:34 +0100, rg <rg1117@hotmail .com> wrote:
                >[color=green]
                > > 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[/color][/color]
                the[color=blue][color=green]
                > > 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[/color][/color]
                sliding[color=blue][color=green]
                > > 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
                > >[/color]
                >
                > 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[/color]
                [color=blue]
                > 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[/color]


                Comment

                • David Hilsee

                  #9
                  Re: template function as function parameter

                  "rg" <rg1117@hotmail .com> wrote in message
                  news:ceqam2$r01 $1@news.freedom 2surf.net...

                  I think you might have overlooked John's request:
                  [color=blue][color=green]
                  > > I think I'd want to see the code that calls transform_slide .[/color][/color]

                  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


                  Comment

                  • rg

                    #10
                    Re: template function as function parameter

                    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<dou ble>(
                    std::plus<doubl e>(), _1,
                    boost::bind(std ::pow, _2, 2)
                    )
                    ) / std::distance(b egin, 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_inser ter(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_inser ter(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" <davidhilseenew s@yahoo.com> wrote in message
                    news:dvSdncTBw8 sSGYzcRVn-qQ@comcast.com. ..[color=blue]
                    > "rg" <rg1117@hotmail .com> wrote in message
                    > news:ceqam2$r01 $1@news.freedom 2surf.net...
                    >
                    > I think you might have overlooked John's request:
                    >[color=green][color=darkred]
                    > > > I think I'd want to see the code that calls transform_slide .[/color][/color]
                    >
                    > Also, it might be good to know exactly where the caller's code, and any[/color]
                    code[color=blue]
                    > it references, is located (defined in "blah.cpp"/declared in "blah.hpp") .
                    >
                    > --
                    > David Hilsee
                    >
                    >[/color]


                    Comment

                    • David Hilsee

                      #11
                      Re: template function as function parameter

                      "rg" <rg1117@hotmail .com> wrote in message
                      news:cf822j$4ig $1@news.freedom 2surf.net...[color=blue]
                      > Hi,
                      >
                      > Sorry for not having replied earlier, been extremely busy. Here is the[/color]
                      code:[color=blue]
                      >
                      > file stats.hpp
                      > {
                      > #insert...
                      > ....
                      >
                      > template <class iterator>
                      > double rms(iterator begin, iterator end) // calculates the Root[/color]
                      Mean[color=blue]
                      > Square Power for some range of values
                      > {
                      > return std::sqrt(
                      > std::accumulate (
                      > begin, end, 0.0, boost::bind<dou ble>(
                      > std::plus<doubl e>(), _1,
                      > boost::bind(std ::pow, _2, 2)
                      > )
                      > ) / std::distance(b egin, 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_inser ter(power),[/color]
                      SLIDE_SIZE );[color=blue]
                      > // 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_inser ter(power),
                      > SLIDE_SIZE,
                      > rms
                      > );
                      >
                      > and tell it to apply the rms algorithm over the sliding frame and insert[/color]
                      the[color=blue]
                      > value into the output iterator.
                      >
                      > Hope it makes sense. Many Thanks for your help.[/color]

                      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(en d,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<dou ble> v;

                      transform_slide (v.begin(),v.en d(),v.begin(),1 ,rms<std::vecto r<double>::iter a
                      tor>);
                      transform_slide (v.begin(),v.en d(),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


                      Comment

                      Working...