CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 10 of 10
  1. #1
    Join Date
    Dec 2004
    Location
    Paso de Robles
    Posts
    296

    Template function not generated?

    I'm trying to make a simple vector class using meta programming. I'm using GCC's 3.3.4 compiler. Here's the code.
    Code:
    template<int N, int I = 0, int Stride = 1>
    class VecOps 
    {
    enum { loopflag = (I < N-1) ? 1 : 0 };
    public:
     template<class expr>
     static inline void Zero(typename expr::iterator v) {
      v[I] = typename expr::value_type();
      VecOps<loopflag*N, loopflag*(I+1)>::Zero(v);
     }
    };
    
    template<>
    class VecOps<0>
    {
    public:
     template<class expr>
     static inline void Zero(typename expr::iterator v) {
     }
    };
    
    template<class T, std::size_t dims>
    class Vector
    {
    public: //exactly the same a boosts array class definitions
     typedef T                                     value_type;            
     typedef T*                                    iterator;              
     typedef const T*                              const_iterator;        
     typedef std::reverse_iterator<iterator>       reverse_iterator;      
     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     typedef T&                                    reference;             
     typedef const T&                              const_reference;       
     typedef std::size_t                           size_type;             
     typedef std::ptrdiff_t                        difference_type;
    private:
     value_type v[dims];
    public:
     Vector() {
      VecOps<dims>::Zero(begin()); //error references this
     }
     
     iterator begin() {
      return &v[0];
     }
     
     iterator end() {
      return &v[dims-1];
     }
    };
    When compiling, I get the following error:
    error: no matching function for call to `VecOps<3, 0, 1>::Zero(int*)
    What am I doing wrong? GCC compiled the blitz++ library perfectly.

  2. #2
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Template function not generated?

    Please include all necessary header files.

    Regards,

    Paul McKenzie

  3. #3
    Join Date
    Apr 1999
    Posts
    27,449

    Re: Template function not generated?

    Also, please include the main() program that instantiates this type.

    Regards,

    Paul McKenzie

  4. #4
    Join Date
    Dec 2004
    Location
    Paso de Robles
    Posts
    296

    Re: Template function not generated?

    OK, here's repost with all the modifications McKenzie asked for.

    Code:
    #include <cstdlib>
    #include <iterator>
    
    template<int N, int I = 0, int Stride = 1>
    class VecOps 
    {
    enum { loopflag = (I < N-1) ? 1 : 0 };
    public:
     template<class expr>
     static inline void Zero(typename expr::iterator v) {
      v[I] = typename expr::value_type();
      VecOps<loopflag*N, loopflag*(I+1)>::Zero(v);
     }
    };
    
    template<>
    class VecOps<0>
    {
    public:
     template<class expr>
     static inline void Zero(typename expr::iterator v) {
     }
    };
    
    template<class T, std::size_t dims>
    class Vector
    {
    public: //exactly the same a boosts array class definitions
     typedef T                                     value_type;            
     typedef T*                                    iterator;              
     typedef const T*                              const_iterator;        
     typedef std::reverse_iterator<iterator>       reverse_iterator;      
     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     typedef T&                                    reference;             
     typedef const T&                              const_reference;       
     typedef std::size_t                           size_type;             
     typedef std::ptrdiff_t                        difference_type;
    private:
     value_type v[dims];
    public:
     Vector() {
      VecOps<dims>::Zero(begin());
     }
     
     iterator begin() {
      return &v[0];
     }
     
     iterator end() {
      return &v[dims-1];
     }
    };
    
    int main(int argc, char *argv[])
    {
     Vector<int, 3> v;
     return EXIT_SUCCESS;
    }

  5. #5
    Join Date
    Oct 2002
    Location
    Singapore
    Posts
    3,128

    Re: Template function not generated?

    This one compile but I am not sure if it meets your needs.

    Code:
    template<int N, int I = 0, int Stride = 1>
    class VecOps 
    {
    enum { loopflag = (I < N-1) ? 1 : 0 };
    public:
     template<class expr>
     static inline void Zero(typename expr &v) {
    	 v.begin()[I] = typename expr::value_type();
      VecOps<loopflag*N, loopflag*(I+1)>::Zero(v);
     }
    };
    
    template<>
    class VecOps<0>
    {
    public:
     template<class expr>
     static inline void Zero(typename expr &v) {
     }
    };
    
    template<class T, std::size_t dims>
    class Vector
    {
    public: //exactly the same a boosts array class definitions
     typedef T                                     value_type;            
     typedef T*                                    iterator;              
     typedef const T*                              const_iterator;        
     typedef std::reverse_iterator<iterator>       reverse_iterator;      
     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     typedef T&                                    reference;             
     typedef const T&                              const_reference;       
     typedef std::size_t                           size_type;             
     typedef std::ptrdiff_t                        difference_type;
    private:
     value_type v[dims];
    public:
     Vector() {
      VecOps<dims>::Zero(*this); //error references this
     }
     
     iterator begin() {
      return &v[0];
     }
     
     iterator end() {
      return &v[dims-1];
     }
    };
    
    int main()
    {
    	Vector<int, 10> v;
    }
    quoted from C++ Coding Standards:

    KISS (Keep It Simple Software):
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.

    Avoid magic number:
    Programming isn't magic, so don't incant it.

  6. #6
    Join Date
    Dec 2004
    Location
    Paso de Robles
    Posts
    296

    Re: Template function not generated?

    Dope, dumb mistake. I know exactly what is happening now. The template is actually generating the function for Vector::iterator. It then looks to find Vector::iterator::iterator. It gets confused and says there is no matching function call. Here's the declaration the compiler sees.

    void VecOps<3, 0, 1>::Zero( int*::iterator v)

    You would think that this would set off all sort of errors, but I guess not.
    Thanks for the help.

  7. #7
    Join Date
    Oct 2002
    Location
    Singapore
    Posts
    3,128

    Re: Template function not generated?

    In fact, both of these lines in your original code fail to compile.

    Code:
     static inline void Zero(typename expr::iterator v) {
      v[I] = typename expr::value_type();
      //...
    The second line requires value_type to be available by expr. Thus, by passing *this into VecOps<...>::Zero(), I am making Vector<...>::value_type available in VecOps<...>::Zero()
    quoted from C++ Coding Standards:

    KISS (Keep It Simple Software):
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.

    Avoid magic number:
    Programming isn't magic, so don't incant it.

  8. #8
    Join Date
    Dec 2004
    Location
    Paso de Robles
    Posts
    296

    Re: Template function not generated?

    I suppose there is only one solution then. That is to add another template argument (maybe a couple because of other things I will be using the class for). Here's what I came up with (I'm not sure if my modification a good).
    Code:
    template<int N, typename expr1, typename expr2 = expr1, int I = 0, int Stride = 1>
    class VecOps 
    {
     enum { loopflag = (I < N-1) ? 1 : 0 };
     typedef typename expr1::iterator iterator;
     typedef typename expr1::const_iterator const_iterator;
     typedef typename expr1::value_type value_type;
     typedef VecOps<loopflag*N, expr1, expr2, loopflag*(I+N)> Next;
    public:
     static inline void Zero(iterator v) {
      v[I] = value_type();
      Next::Zero(v);
     }
    };
    
    template<typename expr1>
    class VecOps<0, expr1>
    {
     typedef typename expr1::iterator iterator;
     typedef typename expr1::const_iterator const_iterator;
     typedef typename expr1::value_type value_type;
    public:
     static inline void Zero(iterator v) {
     }
    };
    
    template<class T, std::size_t dims>
    class Vector
    {
    public: //exactly the same a boosts array class definitions
     typedef T                                     value_type;            
     typedef T*                                    iterator;              
     typedef const T*                              const_iterator;        
     typedef std::reverse_iterator<iterator>       reverse_iterator;      
     typedef std::reverse_iterator<const_iterator> const_reverse_iterator;
     typedef T&                                    reference;             
     typedef const T&                              const_reference;       
     typedef std::size_t                           size_type;             
     typedef std::ptrdiff_t                        difference_type;
    private:
     value_type v[dims];
     typedef VecOps<dims, Vector> Ops;
    public:
     Vector() {
      Ops::Zero(begin());
     }
     
     iterator begin() {
      return &v[0];
     }
     
     iterator end() {
      return &v[dims-1];
     }
    };
    
    int main(int argc, char *argv[])
    {
     Vector<int, 3> v;
     return EXIT_SUCCESS;
    }
    I also discovered that instantiating a template like this does not seems to be possible.
    VecOps<3>::Zero<Vector>(...);
    Is there any reason why this is illegal?

  9. #9
    Join Date
    Oct 2002
    Location
    Singapore
    Posts
    3,128

    Re: Template function not generated?

    Quote Originally Posted by binarybob0001
    I also discovered that instantiating a template like this does not seems to be possible.
    VecOps<3>::Zero<Vector>(...);
    Is there any reason why this is illegal?
    Sorry, I have not idea if the code is legal. Probably you like to test it with Comeau compiler since it is one of the best compiler that conform to the standard.
    quoted from C++ Coding Standards:

    KISS (Keep It Simple Software):
    Correct is better than fast. Simple is better than complex. Clear is better than cute. Safe is better than insecure.

    Avoid magic number:
    Programming isn't magic, so don't incant it.

  10. #10
    Join Date
    Feb 2005
    Location
    "The Capital"
    Posts
    5,306

    Re: Template function not generated?

    Quote Originally Posted by binarybob0001
    I also discovered that instantiating a template like this does not seems to be possible.
    VecOps<3>::Zero<Vector>(...);
    Is there any reason why this is illegal?
    It is invalid as it does not help instantiate neither the first VecOps template nor its specialization. When you say <3> - which template do you expect to get instantiated? First? - No - minimum requirement for that is an int and a type for expr1. Second? - No - minimum requirement for that is a type for expr1. In fact, I think this is wrong:
    Code:
    template<typename expr1>
    class VecOps<0, expr1>
    I think that specialization parameter (second line above) has to be a distinct type. Guys, correct me if I am wrong. Regards.
    Last edited by exterminator; May 15th, 2006 at 07:14 AM. Reason: missed 'n' / 'e'

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