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

    [RESOLVED] Identifying container type in template

    Can anyone think of a way of identifying the container type used, so that a template class can be specialised according to whether the type is vector, list etc.

    This won't compile as the vector requires template arguments.
    Code:
    template <typename T>
    struct Test
    {
        void Function(); // Standard function
    };
    
    template<>
    struct Test<std::vector>
    {
         void Function(); // Optimised function for all vector specialisations
    };
    I'm trying to specialise an STL allocator. If I include the template parameters in the specialisation I end up with a recursive definition.
    i.e. The allocator template requires a container parameter that requires an allocator parameter that requires....
    "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. #2
    Join Date
    Jul 2002
    Location
    Portsmouth. United Kingdom
    Posts
    2,727

    Re: Identifying container type in template

    Actually I think I may be over-complicating it.
    I don't really need to pass the full vector template parameters to the allocator; The standard definition should suffice to specialise the template.
    "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

  3. #3
    Join Date
    Aug 2009
    Location
    Romania->Felnac
    Posts
    48

    Re: Identifying container type in template

    You can do "specialization" for vector<T> something like in this: (just a simple example, but it must compile )
    Code:
    #include <iostream>
    #include <vector>
    
    template <typename T>
    class Test{
    	void Function(); // Standard function
    	T _mem;
    };
    
    template <typename T>
    void Test<T>::Function() {
    	std::cout << _mem;
    }
    
    template<typename T>
    class Test<std::vector<T>> {
    public:
        void Function(); // Optimised function for all vector specialisations
    	std::vector<T> _mem;
    };
    
    template<typename T>
    void Test<std::vector<T>>::Function() {
    	
    	for(std::vector<T>::iterator it = _mem.begin(); it != _mem.end(); ++it)
    		std::cout << *it << " ";
    }
    
    
    
    int main() {
    	std::vector<int> vec;
    	for(int i = 0; i != 10; i++)
    		vec.push_back(i);
    
    	Test<std::vector<int>> t; 
    	t._mem = vec;
    
    	t.Function();
    
    	std::cout << std::endl;
    	std::cin.get();
    	return 0;
    }
    Last edited by Zlatomir; May 18th, 2010 at 05:04 AM.

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

    Re: Identifying container type in template

    I've more or less got what I'm after, but this error message has me stumped at the moment.
    Code:
    error C2664: 'Allocator<TContainer,TValue>::Allocator(const Allocator<TContainer,TValue> &)' : cannot convert parameter 1 from 'Allocator<TContainer,TValue>' to 'const Allocator<TContainer,TValue> &'
    Code:
    #include <vector>
    #include <list>
    
    //*******************
    // Generic Allocator
    //*******************
    template <typename TContainer, typename TValue>
    struct Allocator
    {
        typedef TValue             value_type;
        typedef value_type *       pointer;
        typedef const value_type * const_pointer;
        typedef value_type &       reference;
        typedef const value_type & const_reference;
        typedef std::size_t        size_type;
        typedef std::ptrdiff_t     difference_type;
    
        template<typename U>
        struct rebind
        {
            typedef Allocator<TContainer, U> other;
        };
    
        Allocator();
        Allocator(const Allocator &rhs);
    
        void operator =(const Allocator &);
    
        pointer address(reference x) const;
        const_pointer address(const_reference x) const;
        pointer allocate(size_type n, const_pointer cp = 0);
        void deallocate(pointer p, size_type n);
        size_type max_size() const;
        void construct(pointer p, const value_type &x);
        void destroy(pointer p);
    };
    
    //***************************
    // Allocator for std::vector
    //***************************
    template <typename TValue>
    struct Allocator<std::vector<TValue>, TValue>
    {
        typedef TValue             value_type;
        typedef value_type *       pointer;
        typedef const value_type * const_pointer;
        typedef value_type &       reference;
        typedef const value_type & const_reference;
        typedef std::size_t        size_type;
        typedef std::ptrdiff_t     difference_type;
    
        template<typename U>
        struct rebind
        {
            typedef Allocator<std::vector<U>, U> other;
        };
    
        Allocator();
        Allocator(const Allocator &rhs);
    
        void operator =(const Allocator &);
    
        pointer address(reference x) const;
        const_pointer address(const_reference x) const;
        pointer allocate(size_type n, const_pointer cp = 0);
        void deallocate(pointer p, size_type n);
        size_type max_size() const;
        void construct(pointer p, const value_type &x);
        void destroy(pointer p);
    };
    
    std::vector<int, Allocator<std::vector<int>, int>> test1;
    "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

  5. #5
    Join Date
    Jan 2009
    Posts
    1,689

    Re: Identifying container type in template

    I'm not sure if it helps, but GCC has the typeof function.

  6. #6
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: Identifying container type in template

    Quote Originally Posted by JohnW@Wessex View Post
    I've more or less got what I'm after, but this error message has me stumped at the moment.
    Code:
    error C2664: 'Allocator<TContainer,TValue>::Allocator(const Allocator<TContainer,TValue> &)' : cannot convert parameter 1 from 'Allocator<TContainer,TValue>' to 'const Allocator<TContainer,TValue> &'
    This compiles without errors for me in VS2008.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

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

    Re: Identifying container type in template

    Quote Originally Posted by D_Drmmr View Post
    This compiles without errors for me in VS2008.
    Can you try this line?

    Code:
    std::list<int, Allocator<std::list<int>, int>> test1;
    "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

  8. #8
    Join Date
    Nov 2003
    Posts
    1,902

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

    Re: Identifying container type in template

    Works for me.

    except for

    Code:
    std::vector<int, Allocator<std::vector<int>, int>> test1;
    
    error: `>>' should be `> >' within a nested template argument list
    Your error sounds like, for some reason, you (or your compiler) are trying to pass an argument by value in a copy constructor, which of course is not possible.
    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.

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

    Re: Identifying container type in template

    I didn't get to the bottom of the error.
    In the end I copied the code from my current allocators and modified them, rather than starting from scratch.
    It now compiles fine.

    Here's the cut down code. It'll compile, but the allocators don't do anything.

    Code:
    #pragma warning (disable:4100)
    
    #include <stdlib.h>
    
    #include <vector>
    #include <list>
    
    //*******************
    // Generic Allocator
    //*******************
    template<typename TContainer, typename T, const size_t SIZE>
    class Fixed_Allocator
    {
    private:
    
        static const bool FREE   = false;
        static const bool IN_USE = true;
    
    public:
    
        typedef T                  value_type;
        typedef value_type *       pointer;
        typedef const value_type * const_pointer;
        typedef value_type &       reference;
        typedef const value_type & const_reference;
        typedef std::size_t        size_type;
        typedef std::ptrdiff_t     difference_type;
    
        //*********************************************************************
        // rebind
        //*********************************************************************
        // @short-legal-notice
        //*********************************************************************
        template<typename U>
        struct rebind
        {
            typedef Fixed_Allocator<TContainer, U, SIZE> other;
        };
    
        Fixed_Allocator()
        {
        }
    
        Fixed_Allocator(const Fixed_Allocator &rhs)
        {
        }
    
        template<typename U>
        Fixed_Allocator(const Fixed_Allocator<TContainer, U, SIZE> &rhs)
        {
        }
    
        ~Fixed_Allocator()
        {
        }
    
        pointer address(reference x) const
        {
            return (&x);
        }
    
        const_pointer address(const_reference x) const
        {
            return (x);
        }
    
        pointer allocate(size_type     n,
                         const_pointer cp = 0)
        {
            return (0);
        }
    
        void deallocate(pointer   p,
                        size_type n)
        {
        }
    
        size_type max_size() const
        {
            return (0);
        }
    
        void construct(pointer          p,
                       const value_type &x)
        {
        }
    
        void destroy(pointer p)
        {
        }
    };
    
    template<typename TContainer, typename T, const size_t SIZE>
    inline bool operator ==(const Fixed_Allocator<TContainer, T, SIZE> &,
                            const Fixed_Allocator<TContainer, T, SIZE> &)
    {
        return (false);
    }
    
    template<typename TContainer, typename T, const size_t SIZE>
    inline bool operator !=(const Fixed_Allocator<TContainer, T, SIZE> &,
                            const Fixed_Allocator<TContainer, T, SIZE> &)
    {
        return (true);
    }
    
    //***************************
    // Allocator for std::vector
    //***************************
    template<typename T, const size_t SIZE>
    class Fixed_Allocator<std::vector<T> , T, SIZE>
    {
    public:
        typedef T                  value_type;
        typedef value_type *       pointer;
        typedef const value_type * const_pointer;
        typedef value_type &       reference;
        typedef const value_type & const_reference;
        typedef std::size_t        size_type;
        typedef std::ptrdiff_t     difference_type;
    
        template<typename U>
        struct rebind
        {
            typedef Fixed_Allocator<std::vector<T> , U, SIZE> other;
        };
    
        Fixed_Allocator()
        {
        }
    
        Fixed_Allocator(const Fixed_Allocator &rhs)
        {
        }
    
        template<typename U>
        Fixed_Allocator(const Fixed_Allocator<std::vector<T> , U, SIZE> &rhs)
        {
        }
    
        ~Fixed_Allocator()
        {
        }
    
        pointer address(reference x) const
        {
            return (&x);
        }
    
        const_pointer address(const_reference x) const
        {
            return (x);
        }
    
        pointer allocate(size_type     n,
                         const_pointer cp = 0)
        {
            return (0);
        }
    
        void deallocate(pointer   p,
                        size_type n)
        {
        }
    
        size_type max_size() const
        {
            return (0);
        }
    
        void construct(pointer          p,
                       const value_type &x)
        {
        }
    
        void destroy(pointer p)
        {
        }
    };
    
    template<typename T, const size_t SIZE>
    inline bool operator ==(const Fixed_Allocator<std::vector<T> , T, SIZE> &,
                            const Fixed_Allocator<std::vector<T> , T, SIZE> &)
    {
        return (false);
    }
    
    template<typename T, const size_t SIZE>
    inline bool operator !=(const Fixed_Allocator<std::vector<T> , T, SIZE> &,
                            const Fixed_Allocator<std::vector<T> , T, SIZE> &)
    {
        return (true);
    }
    
    template<>
    class Fixed_Allocator<void, void, 0>
    {
        typedef void         value_type;
        typedef void *       pointer;
        typedef const void * const_pointer;
    
        template<typename U>
        struct rebind
        {
            typedef Fixed_Allocator<void, U, 0> other;
        };
    };
    
    int main()
    {
        std::vector < int, Fixed_Allocator < std::vector<int> , int, 10 >> test1;
        std::list < int, Fixed_Allocator < std::list<int> , int, 10 >> test2;
    }
    "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

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

    Re: Identifying container type in template

    So... Is the problem fixed? I mean there isn't any new question...

    Where you able to determine which line of code was the culprit? You didn't give us the error line number, nor the implementation code, so not much we could go on.

    Regards,
    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.

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

    Re: Identifying container type in template

    In the original code, the error indicated by the compiler was deep in the definition of one of the STL source files, and therefore, virtually incomprehensible.

    And yes, problem sorted.
    "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

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

    Re: Identifying container type in template

    Quote Originally Posted by JohnW@Wessex View Post
    In the original code, the error indicated by the compiler was deep in the definition of one of the STL source files, and therefore, virtually incomprehensible.

    And yes, problem sorted.
    FYI, the error in your original code was the lack of the "template<typename U> Allocator( const Allocator<TContainer , U> &rhs);" ctor (indeed the std::vector instantiation did not fail because the allocator is not rebinded in that case ).

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