CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 8 of 8
  1. #1
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557

    Array of constant values as template parameter

    Hello,

    It's been a while since I checked in here.

    Is it possible to use an array of constant values as a template parameter. I am writing preliminary benchmark code for ISO/IEC 14882:2011, so I could also use std::array or std::initializer_list.

    In the mathematical template below, I use integer coefficients. The template has order 3.

    Code:
    template<const std::size_t order,
             const std::uint_least16_t B0,
             const std::uint_least16_t B1,
             const std::uint_least16_t B2,
             const std::uint_least16_t B3>
    struct order3_math
    {
      // Do order-3 math.
    };
    If I want to write more generic code, I could use order N and an array-type template parameter. But it does not work with compilers like VS2010 and GCC 4.6.x. Can it work or *should* something like this ever work without variadic templates?

    Code:
    // Can I do anything like this?
    template<const std::size_t order,
             const std::array<std::uint_least16_t, order> coefficients>
    struct orderN_math
    {
      // Do order-N math.
    };
    Thank you.
    Sincerely, Chris.
    Last edited by dude_1967; September 19th, 2011 at 07:40 AM. Reason: Simplified the code example.
    You're gonna go blind staring into that box all day.

  2. #2
    Join Date
    Oct 2008
    Posts
    1,456

    Re: Array of constant values as template parameter

    AFAIK, you can declare non type template parameters of array type, provided they have external linkage. Something like

    Code:
    template<std::size_t order, std::uint_least16_t coefficients[order]>
    struct orderN_math
    {
    	// ...
    };
    
    int a[3];
    orderN_math<3,a> b;
    is this what you're looking for ? I ask, because IMHO if the intent is to emulate variadic templates then a boost MPL based solution would be better ...

  3. #3
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557

    Re: Array of constant values as template parameter

    No, that one did not work.

    But this cool tidbit works with GCC. I tested it with GCC 4.5.2

    Code:
    #include <initializer_list>
    
    template<const unsigned order>
    struct orderN_math
    {
      static unsigned do_math(const std::initializer_list<unsigned>& coefficients)
      {
        return std::accumulate(coefficients.begin(), coefficients.end(), 0u);
      }
    };
    
    const unsigned sum = orderN_math<3u>::do_math({ 1u, 3u, 3u, 1u });
    VS2010 does not yet support <initializer_list>. But I don't really need it, as I'm using GCC.

    Not exactly what I wanted, but a good start nonetheless.

    At this time, I am investigating compiler efficiency for real-time embedded systems using solely pure language attributes and would prefer not to bind anything from boost into this investigation.

    Thanks, Chris.
    You're gonna go blind staring into that box all day.

  4. #4
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Array of constant values as template parameter

    Quote Originally Posted by dude_1967 View Post
    No, that one did not work.

    But this cool tidbit works with GCC. I tested it with GCC 4.5.2

    Code:
    #include <initializer_list>
    
    template<const unsigned order>
    struct orderN_math
    {
      static unsigned do_math(const std::initializer_list<unsigned>& coefficients)
      {
        return std::accumulate(coefficients.begin(), coefficients.end(), 0u);
      }
    };
    
    const unsigned sum = orderN_math<3u>::do_math({ 1u, 3u, 3u, 1u });
    VS2010 does not yet support <initializer_list>. But I don't really need it, as I'm using GCC.

    Not exactly what I wanted, but a good start nonetheless.

    At this time, I am investigating compiler efficiency for real-time embedded systems using solely pure language attributes and would prefer not to bind anything from boost into this investigation.

    Thanks, Chris.
    Not sure what you are trying to do. Can't you do the same with a plain old point, or a reference to a fixed size array?

    Code:
    #include<iostream>
    #include<algorithm>
    #include<numeric>
    
    template<const unsigned order>
    struct orderN_math
    {
      //ONLY accepts arrays, and only of size4.
      static unsigned do_math1(const unsigned int (&coefficients) [order])
      {
        return std::accumulate(coefficients, coefficients+order, 0u);
      }
    
      //Accpets anything, you are responsible for making sure it is the right type.
      static unsigned do_math2(const unsigned int* coefficients)
      {
        return std::accumulate(coefficients, coefficients+order, 0u);
      }
    };
    
    int main()
    {
      unsigned a[] = {1u, 3u, 3u, 1u};
      unsigned* p = a;
      const unsigned sum11 = orderN_math<4u>::do_math1(a);
      //const unsigned sum12 = orderN_math<4u>::do_math1(p);
    
      const unsigned sum21 = orderN_math<4u>::do_math2(a);
      const unsigned sum22 = orderN_math<4u>::do_math2(p);
    }
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  5. #5
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557

    Re: Array of constant values as template parameter

    Quote Originally Posted by monarch_dodra View Post
    Not sure what you are trying to do. Can't you do the same with a plain old point, or a reference to a fixed size array?
    With pointer : Yes and no.
    With std::array : Yes.

    I am simultaneously investigating compiler-time unrolling in combination with compiler-time constants. The constants in a const std::initializer_list or a const std::array can be easily identified by the compiler and used in constant folding. They are also available for forced loop-unrolling with meta-programming.

    The constants in a pointer are less available to the compiler.

    These investigations go deep into compiler optimization methods. It's not really about finding the most terse code, rather the combination of terse, unrollable and ultra-fast.

    Sincerely, Chris.
    You're gonna go blind staring into that box all day.

  6. #6
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: Array of constant values as template parameter

    Quote Originally Posted by dude_1967 View Post
    The constants in a pointer are less available to the compiler.
    Well, an initializer list is a convenience class that can be used to uniformly initialize containers, or pass arguments. While the compiler can inline its construction, and knows its size, once passed as an argument, it is a pure run-time object, no different than, say, a vector.

    the template parameter "order" is a compile time constant that can be exploited by the compiler (and the one used in my code), to exploit loop unrolling. "coefficients.begin(), coefficients.begin() + order" can be unrolled. "coefficients.begin(), coefficients.end()" can't be unrolled though...

    If you were to use and std::array though, then it would work, but you would HAVE to make do_math a sub-template:

    Code:
    #include <array>
    #include<numeric>
    
    template<unsigned order>
    struct orderN_math
    {
      template<const unsigned order2>
      static unsigned do_math(const std::array<const unsigned, order2>& coefficients)
      {
        return std::accumulate(coefficients.begin(), coefficients.begin() + order2, 0u);
      }
    };
    
    
    int main()
    {
      std::array<const unsigned, 4> a{ 1u, 3u, 3u, 1u };
      const unsigned sum = orderN_math<2u>::do_math(a);
    }
    Last edited by monarch_dodra; September 19th, 2011 at 10:09 AM.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  7. #7
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557

    Re: Array of constant values as template parameter

    Quote Originally Posted by monarch_dodra View Post
    initializer list... once passed as an argument, it is a pure run-time object...

    the template parameter "order" is a compile time constant that can be exploited by the compiler...

    If you were to use and std::array though, then it would work, but you would HAVE to make do_math a sub-template:
    Yes. I agree, I agree and I agree with all three sections of your text.

    And I really do like your C-style array suggestion. In fact, I'm just in the process of seeing how it is unrolled or even forcing the unroll.

    Thank you.

    Sometimes I take the exercise even further by *forcing* loop unrolling using meta-programming for things like accumulation and inner products. And this is what I am also looking at. It's pretty amazing what these C++ compilers can do. They really squeeze the code at high optimization level. Fascinating.

    Thank you.
    Sincerely Chris.
    You're gonna go blind staring into that box all day.

  8. #8
    Join Date
    Jun 2002
    Location
    Germany
    Posts
    1,557

    Re: Array of constant values as template parameter

    Oh yeah,

    And I also forgot to add that one of the real tricks is finding reliable ways to coerce the compiler into constant-folding the coefficients, not merely getting the math unrolled. This allows fast shift-and-add instead of multiply when, for example, dealing with an inner product.

    Some ultra-clever compilers like GCC will *know* the constant values of an initializer list if these are passed as compile-time constants to the subroutine in curly braces.

    Again, simply great compiler technologies these days. I can play all day and still find new stuff.

    Sincerely, Chris.
    You're gonna go blind staring into that box all day.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured