Unrolling loops using templates

Discussion in 'C++' started by Ashley, Mar 3, 2011.

  1. Ashley

    Ashley Guest

    I'm trying to unroll a loop that prints down numbers from the given
    number down to 0. I get the following error on Sun C++ 5.5 Patch
    113817-12.

    -------------------------
    "tmp.cpp", line 15: Error: explicit specialization is not allowed in
    the current scope.
    "tmp.cpp", line 24: Where: While specializing
    "printDownContainer<int>".
    "tmp.cpp", line 24: Where: Specialized in non-template code.
    "tmp.cpp", line 24: Error: Template parameter T requires a type
    argument.
    -------------------------

    How can I correct this? I want to generalize the type of the counter
    i. Here's the code.

    -------------------------
    #include <iostream>

    template< typename T >
    struct printDownContainer
    {
    template< T i >
    struct printDown {
    static void run(void) {
    std::cout << i << "\n";
    printDown< i - 1 >::run();
    }
    };

    template< >
    struct printDown< 0 > {
    static void run(void) {
    std::cout << 0 << "\n";
    }
    };
    };

    int main(void)
    {
    printDownContainer< int >::printDown< 10 >::run();

    return 0;
    }
    -------------------------

    Thanks in advance.
    Ashley, Mar 3, 2011
    #1
    1. Advertising

  2. On 3/3/2011 12:32 PM, Ashley wrote:
    > I'm trying to unroll a loop that prints down numbers from the given
    > number down to 0. I get the following error on Sun C++ 5.5 Patch
    > 113817-12.
    >
    > -------------------------
    > "tmp.cpp", line 15: Error: explicit specialization is not allowed in
    > the current scope.
    > "tmp.cpp", line 24: Where: While specializing
    > "printDownContainer<int>".
    > "tmp.cpp", line 24: Where: Specialized in non-template code.
    > "tmp.cpp", line 24: Error: Template parameter T requires a type
    > argument.
    > -------------------------
    >
    > How can I correct this? I want to generalize the type of the counter
    > i. Here's the code.
    >
    > -------------------------
    > #include<iostream>
    >
    > template< typename T>
    > struct printDownContainer
    > {
    > template< T i>
    > struct printDown {
    > static void run(void) {
    > std::cout<< i<< "\n";
    > printDown< i - 1>::run();
    > }
    > };
    >
    > template< >
    > struct printDown< 0> {
    > static void run(void) {
    > std::cout<< 0<< "\n";
    > }
    > };
    > };
    >
    > int main(void)
    > {
    > printDownContainer< int>::printDown< 10>::run();
    >
    > return 0;
    > }
    > -------------------------


    You can't define/declare a specialization in the class template body.
    And you can't specialize a member without specializing the class. What
    you could do is to extract your 'printDown' functionality into a
    separate template with two arguments and provide a partial
    specialization for it:

    template<class T, T i> struct printDownHelper {
    ...
    };

    template<class T> struct printDownHelper<T,0> {
    ...
    };

    And then in your 'printDownContainer' just forward the request to the
    helper:

    tempate<class T> struct printDownContainer {
    tempate<T i> printDown {
    static void run() {
    printDownHelper<T,i>::doit();
    }
    }
    };

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Mar 3, 2011
    #2
    1. Advertising

  3. Ashley

    Ashley Guest

    I just modified my code to try that, but I get the following error on
    the "template<class T> struct printDownHelper<T,0> {" line.

    Error: The type of specialized argument i is dependent on another
    argument.

    Is this because my compiler is old? Here's the new template code.

    -------------------------
    template< class T, T i >
    struct printDownHelper {
    static void run(void) {
    std::cout << i << "\n";
    printDownHelper< T, i - 1 >::run();
    }
    };

    template< class T >
    struct printDownHelper< T, 0 > {
    static void run(void) {
    std::cout << 0 << "\n";
    }
    };

    template< class T >
    struct printDownContainer {
    template< T i >
    struct printDown {
    static void run (void) {
    printDownHelper< T, i >::run();
    }
    };
    };
    -------------------------

    Thanks in advance.


    On Mar 3, 1:14 pm, Victor Bazarov <> wrote:
    > On 3/3/2011 12:32 PM, Ashley wrote:
    >
    >
    >
    > > I'm trying to unroll a loop that prints down numbers from the given
    > > number down to 0.  I get the following error on Sun C++ 5.5 Patch
    > > 113817-12.

    >
    > > -------------------------
    > > "tmp.cpp", line 15: Error: explicit specialization is not allowed in
    > > the current scope.
    > > "tmp.cpp", line 24:     Where: While specializing
    > > "printDownContainer<int>".
    > > "tmp.cpp", line 24:     Where: Specialized in non-template code.
    > > "tmp.cpp", line 24: Error: Template parameter T requires a type
    > > argument.
    > > -------------------------

    >
    > > How can I correct this?  I want to generalize the type of the counter
    > > i.  Here's the code.

    >
    > > -------------------------
    > > #include<iostream>

    >
    > > template<  typename T>
    > > struct printDownContainer
    > > {
    > >      template<  T i>
    > >      struct printDown {
    > >          static void run(void) {
    > >              std::cout<<  i<<  "\n";
    > >              printDown<  i - 1>::run();
    > >          }
    > >      };

    >
    > >      template<  >
    > >      struct printDown<  0>  {
    > >          static void run(void) {
    > >              std::cout<<  0<<  "\n";
    > >          }
    > >      };
    > > };

    >
    > > int main(void)
    > > {
    > >      printDownContainer<  int>::printDown<  10>::run();

    >
    > >      return 0;
    > > }
    > > -------------------------

    >
    > You can't define/declare a specialization in the class template body.
    > And you can't specialize a member without specializing the class.  What
    > you could do is to extract your 'printDown' functionality into a
    > separate template with two arguments and provide a partial
    > specialization for it:
    >
    > template<class T, T i> struct printDownHelper {
    >     ...
    >
    > };
    >
    > template<class T> struct printDownHelper<T,0> {
    >     ...
    >
    > };
    >
    > And then in your 'printDownContainer' just forward the request to the
    > helper:
    >
    >    tempate<class T> struct printDownContainer {
    >        tempate<T i> printDown {
    >            static void run() {
    >               printDownHelper<T,i>::doit();
    >            }
    >        }
    >    };
    >
    > V
    > --
    > I do not respond to top-posted replies, please don't ask
    Ashley, Mar 3, 2011
    #3
  4. Ashley

    Ashley Guest

    Looks like the problem now is that I need to specialize i in
    printDownHelper while saying that it's of type T. How can I do that?
    Is there a way to annotate the type of 0 in the partial
    specialization?


    On Mar 3, 1:29 pm, Ashley <> wrote:
    > I just modified my code to try that, but I get the following error on
    > the "template<class T> struct printDownHelper<T,0> {" line.
    >
    > Error: The type of specialized argument i is dependent on another
    > argument.
    >
    > Is this because my compiler is old?  Here's the new template code.
    >
    > -------------------------
    > template< class T, T i >
    > struct printDownHelper {
    >     static void run(void) {
    >         std::cout << i << "\n";
    >         printDownHelper< T, i - 1 >::run();
    >     }
    >
    > };
    >
    > template< class T >
    > struct printDownHelper< T, 0 > {
    >     static void run(void) {
    >         std::cout << 0 << "\n";
    >     }
    >
    > };
    >
    > template< class T >
    > struct printDownContainer {
    >     template< T i >
    >     struct printDown {
    >         static void run (void) {
    >             printDownHelper< T, i >::run();
    >         }
    >     };};
    >
    > -------------------------
    >
    > Thanks in advance.
    >
    > On Mar 3, 1:14 pm, Victor Bazarov <> wrote:
    >
    > > On 3/3/2011 12:32 PM, Ashley wrote:

    >
    > > > I'm trying to unroll a loop that prints down numbers from the given
    > > > number down to 0.  I get the following error on Sun C++ 5.5 Patch
    > > > 113817-12.

    >
    > > > -------------------------
    > > > "tmp.cpp", line 15: Error: explicit specialization is not allowed in
    > > > the current scope.
    > > > "tmp.cpp", line 24:     Where: While specializing
    > > > "printDownContainer<int>".
    > > > "tmp.cpp", line 24:     Where: Specialized in non-template code.
    > > > "tmp.cpp", line 24: Error: Template parameter T requires a type
    > > > argument.
    > > > -------------------------

    >
    > > > How can I correct this?  I want to generalize the type of the counter
    > > > i.  Here's the code.

    >
    > > > -------------------------
    > > > #include<iostream>

    >
    > > > template<  typename T>
    > > > struct printDownContainer
    > > > {
    > > >      template<  T i>
    > > >      struct printDown {
    > > >          static void run(void) {
    > > >              std::cout<<  i<<  "\n";
    > > >              printDown<  i - 1>::run();
    > > >          }
    > > >      };

    >
    > > >      template<  >
    > > >      struct printDown<  0>  {
    > > >          static void run(void) {
    > > >              std::cout<<  0<<  "\n";
    > > >          }
    > > >      };
    > > > };

    >
    > > > int main(void)
    > > > {
    > > >      printDownContainer<  int>::printDown<  10>::run();

    >
    > > >      return 0;
    > > > }
    > > > -------------------------

    >
    > > You can't define/declare a specialization in the class template body.
    > > And you can't specialize a member without specializing the class.  What
    > > you could do is to extract your 'printDown' functionality into a
    > > separate template with two arguments and provide a partial
    > > specialization for it:

    >
    > > template<class T, T i> struct printDownHelper {
    > >     ...

    >
    > > };

    >
    > > template<class T> struct printDownHelper<T,0> {
    > >     ...

    >
    > > };

    >
    > > And then in your 'printDownContainer' just forward the request to the
    > > helper:

    >
    > >    tempate<class T> struct printDownContainer {
    > >        tempate<T i> printDown {
    > >            static void run() {
    > >               printDownHelper<T,i>::doit();
    > >            }
    > >        }
    > >    };

    >
    > > V
    > > --
    > > I do not respond to top-posted replies, please don't ask

    >
    >
    Ashley, Mar 3, 2011
    #4
  5. Ashley

    Marc Guest

    Ashley wrote:

    > -------------------------
    > template< class T, T i >
    > struct printDownHelper {
    > static void run(void) {
    > std::cout << i << "\n";
    > printDownHelper< T, i - 1 >::run();
    > }
    > };
    >
    > template< class T >
    > struct printDownHelper< T, 0 > {
    > static void run(void) {
    > std::cout << 0 << "\n";
    > }
    > };
    > -------------------------


    Try this instead:

    template< class T, T i, bool b=(i==0) >
    struct printDownHelper {
    static void run(void) {
    std::cout << i << "\n";
    printDownHelper< T, i - 1 >::run();
    }
    };

    template< class T, T i >
    struct printDownHelper< T, i, true > {
    static void run(void) {
    std::cout << 0 << "\n";
    }
    };
    Marc, Mar 3, 2011
    #5
  6. Ashley

    Ashley Guest

    Wow, I didn't know you could do that. Thanks, that's what I'm looking
    for.
    I beginning to like this -- it's getting more & more similar to
    Prolog's pattern matching.

    On Mar 3, 5:28 pm, Marc <> wrote:
    > Ashley  wrote:
    > > -------------------------
    > > template< class T, T i >
    > > struct printDownHelper {
    > >     static void run(void) {
    > >         std::cout << i << "\n";
    > >         printDownHelper< T, i - 1 >::run();
    > >     }
    > > };

    >
    > > template< class T >
    > > struct printDownHelper< T, 0 > {
    > >     static void run(void) {
    > >         std::cout << 0 << "\n";
    > >     }
    > > };
    > > -------------------------

    >
    > Try this instead:
    >
    > template< class T, T i, bool b=(i==0) >
    > struct printDownHelper {
    >     static void run(void) {
    >         std::cout << i << "\n";
    >         printDownHelper< T, i - 1 >::run();
    >     }
    >
    > };
    >
    > template< class T, T i >
    > struct printDownHelper< T, i, true > {
    >     static void run(void) {
    >         std::cout << 0 << "\n";
    >     }
    >
    > };
    >
    >
    Ashley, Mar 4, 2011
    #6
  7. Ashley

    Gil Guest

    On Mar 3, 12:32 pm, Ashley <> wrote:
    > I'm trying to unroll a loop that prints down numbers from the given
    > number down to 0.
    > Thanks in advance.


    using namespace boost;

    mpl::for_each< mpl::range_c<int,0,10> >(
    std::cout << lambda::_1 << " "
    );
    Gil, Mar 6, 2011
    #7
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. John Edwards
    Replies:
    5
    Views:
    362
    Thomas Matthews
    Jul 7, 2003
  2. =?ISO-8859-1?Q?Per_Nordl=F6w?=

    g++ loop unrolling performance

    =?ISO-8859-1?Q?Per_Nordl=F6w?=, Aug 31, 2004, in forum: C++
    Replies:
    1
    Views:
    989
    Jack Klein
    Sep 1, 2004
  3. Richard Cavell

    Unrolling a loop

    Richard Cavell, Feb 23, 2005, in forum: C++
    Replies:
    3
    Views:
    2,218
    Phillip Jordan
    Feb 23, 2005
  4. V

    unrolling nested for-loop

    V, May 10, 2008, in forum: C Programming
    Replies:
    10
    Views:
    1,070
    Willem
    May 10, 2008
  5. mark

    ultra-fast loop unrolling with g++ -O3

    mark, Jun 12, 2008, in forum: C Programming
    Replies:
    2
    Views:
    735
    santosh
    Jun 12, 2008
Loading...

Share This Page