CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Page 2 of 2 FirstFirst 12
Results 16 to 22 of 22
  1. #16
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Template specialisation of template class member function

    Each type of STL container iterator has certain properties. std::vector's iterators are 'random access' (you can move the iterator any number of positions at one go) while std:list's are bidirectional (foreward/backward, one position at a time). Pointers are also random access iterators.

    When writing a template that accepts iterators you may need to know what type of iterator you are dealing with, as you may be able to write a more efficient algorithm with, say, random access iterators. The iterator_traits template class allows you to discover this information at compile time and create specialisations of templated classes by checking the iterator's 'tag'.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  2. #17
    Join Date
    Nov 2006
    Location
    Essen, Germany
    Posts
    1,344

    Re: Template specialisation of template class member function

    Speed.
    One memcpy of 100 elements is probably faster than a loop with 100 assignments.
    What about the type traits Souldog mentioned? Using traits will speed up your assign method because it´s evaluated at compile time and you don´t need the is_primitive call (though I must admit I don´t fully understand what is_primitive does).
    One drawback of using type_traits is that you have to provide them for every type you´re going to use.
    - Guido

  3. #18
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Template specialisation of template class member function

    Quote Originally Posted by GNiewerth
    One drawback of using type_traits is that you have to provide them for every type you´re going to use.
    Not necessarily. You can define a default template for something like Is_Pod where the falue is 'false', then specialise the template for POD types. When you use it for a new class or structure type it will automatically acquire the 'false' value.
    "It doesn't matter how beautiful your theory is, it doesn't matter how smart you are. If it doesn't agree with experiment, it's wrong."
    Richard P. Feynman

  4. #19
    Join Date
    Nov 2006
    Location
    Essen, Germany
    Posts
    1,344

    Re: Template specialisation of template class member function

    Quote Originally Posted by JohnW@Wessex
    Not necessarily. You can define a default template for something like Is_Pod where the falue is 'false', then specialise the template for POD types. When you use it for a new class or structure type it will automatically acquire the 'false' value.
    Hehe, yes, I´m aware of that. But to use the power of memcpy you have to provide a type_traits specialization for your class.
    - Guido

  5. #20
    Join Date
    Aug 2005
    Location
    LI, NY
    Posts
    576

    Re: Template specialisation of template class member function

    Quote Originally Posted by PredicateNormative
    Ok, it's a bit convoluted but it works. If you think any of it is a bad idea, or could be done in a better way then let me know.

    I defined a helper class:
    Code:
    template <typename IteratorCategory_, typename Buffer_>
    class AssignmentHelper
    {
    public:
      template <typename Iter_>
      void assign(Iter_ first, Iter_ last, Buffer_& buffer)
      {
        buffer.assignUsingIteration(first, last);
      }
    };
    which I partially specialised as follows:

    Code:
    template <typename Buffer_>
    class AssignmentHelper<std::random_access_iterator_tag, Buffer_>
    {
    public:
        template <typename Iter_>
        void assign(Iter_ first, Iter_ last, Buffer_& buffer)
        {
          buffer.assignUsingMemcpy(first, last);
        }
    };
    I then created a function to test the value_type of my BufferClass:

    Code:
    //A minor modification of how Andrei Alexandrescu achieves 
    //primative data type recognition in his book "Modern C++ Design"
    template<typename T>
    bool isPrimitive(T)
    {
        typedef char Small;
        typedef char (&Big)[2];
        Small Test(long double);
        Big Test(...);
        return sizeof( Test(T()) ) == sizeof(Small) ;
    }
    Finally, I redefined my BufferClass as follows:

    Code:
    template <typename T>
    class BufferClass
    {
    public:
      typedef T value_type;
    
      template <typename Iter_>
      void assign(Iter_ first, Iter_ last)
      {
        AssignmentHelper<typename std::iterator_traits<Iter_>::iterator_category, BufferClass<T> > assignHelper;
        assignHelper.assign(first, last, *this);
      }
    
      template <typename Iter_>
      void assignUsingMemcpy(Iter_ first, Iter_ last)
      {
        if(!isPrimitive(value_type())) 
        {
          std::cout << "Buffer<T> value_type is non-POD: ";
          assignUsingIteration(first, last);
        }
        else
        {
          std::cout << "Can use memcpy" << std::endl;
        }
      }
    
      template <typename Iter_>
      void assignUsingIteration(Iter_ first, Iter_ last)
      {
        std::cout << "Can't use memcpy" << std::endl;
      }
    
      //...
    
    private:
      //...
    };
    Now, when I run it with:

    Code:
    int main()
    {
      std::vector<double> vec;
      std::list<double> lst;
    
      BufferClass<double> test;
      
      std::cout << "Test with std::list:\n  -> ";
      test.assign(lst.begin(),lst.end());
    
      std::cout << "Test with std::vector:\n  -> ";
      test.assign(vec.begin(),vec.end());
    
      std::vector< std::vector<double> > vecNonPod;
      BufferClass<std::vector<double> > nonPodTest;
    
      std::cout << "Test with std::vector with non-POD value_type:\n  -> ";
      nonPodTest.assign(vecNonPod.begin(),vecNonPod.end());
    
    }
    I get the following heart warming output:

    Code:
    Test with std::list:
      -> Can't use memcpy
    Test with std::vector:
      -> Can use memcpy
    Test with std::vector with non-POD value_type:
      -> Buffer<T> value_type is non-POD: Can't use memcpy
    I would appreciate any feedback.
    I do not think it is safe to assume that all random access iterators will iterate over contiguous memory, just that they provide constant-time access to any element in the collection. If a random access iterator operates on a single channel of an interlaced buffer, for instance, memcpy would not work correctly. I think your best bet would be the specialize for those iterators you know to be contiguous, such vector::iterator and string::iterator. This could even be wrapped up tidily in something like an is_contiguous type trait.
    - Alon

  6. #21
    Join Date
    Apr 2004
    Location
    England, Europe
    Posts
    2,492

    Re: Template specialisation of template class member function

    In fact std::string::iterator IS an example of an iterator which is not guaranteed to iterate over contiguous memory.
    My hobby projects:
    www.rclsoftware.org.uk

  7. #22
    Join Date
    Aug 2005
    Location
    LI, NY
    Posts
    576

    Re: Template specialisation of template class member function

    Quote Originally Posted by Zaccheus
    In fact std::string::iterator IS an example of an iterator which is not guaranteed to iterate over contiguous memory.
    Well, it's a debatable point, depending on what kind of guarantee you're looking for. The current standard does not require that strings be contiguous, but future standards will and most if not all current implementations do.
    - Alon

Page 2 of 2 FirstFirst 12

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