Thread: templated class type conversion

  1. #1
    Registered User
    Join Date
    Apr 2009
    Posts
    11

    templated class type conversion

    Hey, I've created a templated Vector class and I want to be able to overload addition/multiplication operators etc. But I'm having a problem when combining different datatypes, for example Vector<double> * Vector<int>. The best solution I could think of was the following:

    Code:
    template <typename T, typename U>
    inline friend double operator*(const Vector<T>& lhs, const Vector<U>& rhs)
    { return (lhs[0]*rhs[0] + lhs[1]*rhs[1]); }
    This works for the usual case of having a T=double and U=int, or T=int and U=double. But it's not as general as I'd like. Is there a better solution to this (i'd assume) common problem?

  2. #2
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    Well, it's hard to know what type you'd want to end up with, which I suppose is your problem. I'd probably add that as a templatized parameter as well. Or: standard containers like std::vector provide a value_type typedef, so that you can use e.g.
    Code:
    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    template <typename VectorType>
    inline typename VectorType::value_type dotProduct(const VectorType &one, const VectorType &two) {
        typename VectorType::value_type value = 0;
        for(typename VectorType::size_type i = 0;
            i < std::min(one.size(), two.size()); i ++) {
            
            value += one[i] * two[i];
        }
        return value;
    }
    
    int main() {
        std::vector<double> a, b;
        
        a.push_back(1);
        a.push_back(3);
        
        b.push_back(1);
        b.push_back(0.5);
        
        std::cout << dotProduct(a, b) << std::endl;
        
        return 0;
    }
    That's pretty ugly. But you get the idea. And if you wanted to be really general you could get even uglier:
    Code:
    #include <iostream>
    #include <algorithm>
    #include <vector>
    
    template <typename TypeOne, typename TypeTwo, typename ResultType>
    inline ResultType dotProduct(const TypeOne &one, const TypeTwo &two) {
        ResultType value = 0;
        for(std::size_t i = 0; i < std::min(one.size(), two.size()); i ++) {
            value += one[i] * two[i];
        }
        return value;
    }
    
    int main() {
        std::vector<double> a, b;
        
        a.push_back(1);
        a.push_back(3);
        
        b.push_back(1);
        b.push_back(0.5);
        
        std::cout << dotProduct<std::vector<double>, std::vector<double>, double>(a, b) << std::endl;
        
        return 0;
    }
    I'd definitely suggest that you let the types be inferred whenever possible, e.g. let the return type be the value_type of the first parameter or something. Also you'll notice that my code works for any data type (std::vector, maybe your Vector) that supports an [] operator and .size() and has a value_type. You can make your life easier if you assume a Vector.

    Finally: I wouldn't overload a * operator if it has complicated semantics like copying the value type of the first argument. I'd probably call it by a custom name. But that's up to you.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  3. #3
    Officially An Architect brewbuck's Avatar
    Join Date
    Mar 2007
    Location
    Portland, OR
    Posts
    7,396
    Quote Originally Posted by kezman View Post
    This works for the usual case of having a T=double and U=int, or T=int and U=double. But it's not as general as I'd like. Is there a better solution to this (i'd assume) common problem?
    In what way is it not general enough? This should work for any types T and U as far as I can tell.
    Code:
    //try
    //{
    	if (a) do { f( b); } while(1);
    	else   do { f(!b); } while(1);
    //}

  4. #4
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    I think the main problem is that it returns double. If you multiply a Vector<int> by a Vector<int> that might not be what you expect.
    dwk

    Seek and ye shall find. quaere et invenies.

    "Simplicity does not precede complexity, but follows it." -- Alan Perlis
    "Testing can only prove the presence of bugs, not their absence." -- Edsger Dijkstra
    "The only real mistake is the one from which we learn nothing." -- John Powell


    Other boards: DaniWeb, TPS
    Unofficial Wiki FAQ: cpwiki.sf.net

    My website: http://dwks.theprogrammingsite.com/
    Projects: codeform, xuni, atlantis, nort, etc.

  5. #5
    Master Apprentice phantomotap's Avatar
    Join Date
    Jan 2008
    Posts
    5,108
    O_o

    So you say you need a facility to selectively enlarge (as according to the implicit casting hierarchy) a set of types obtained from template parameters? There's a `Boost' for that!




    Seriously, you can do this yourself building on the traits mechanism, but you better be ready for a lot tedious code. It is all easy code, but you can expect a lot of it.

    *shrug*

    Or just use `double' and demand that any types `T' and `U' be convertible to and from double.

    Soma

  6. #6
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    How about some C++0x magic?
    Code:
    #include <vector>
    
    template <typename T, typename U>
    auto operator * (const std::vector<T>& lhs, const std::vector<U>& rhs) -> decltype(lhs[0]*rhs[0] + lhs[1]*rhs[1])
    {
    	return (lhs[0]*rhs[0] + lhs[1]*rhs[1]); 
    }
    
    int main()
    {
    	std::vector<double> a;
    	std::vector<int> b;
    	a.push_back(1);
    	a.push_back(1);
    	b.push_back(2);
    	b.push_back(2);
    	double d = a*b;
    	return 0;
    }
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

  7. #7
    Registered User
    Join Date
    Apr 2009
    Posts
    11
    Thanks for the suggestions guys. The C++0x auto feature is looking pretty attractive right now. Is it safe start using C++0x? Im assuming it'll be backwards compatible with the previous standard, so I'll be able to pick and choose which features I want to use within my code?

  8. #8
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    Yeah, it's backwards compatible. We have two big compilers that supports these features, which are Visual C++ (2010) and GCC (4.x and up).
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Templated Abstract Class...
    By yaya in forum C++ Programming
    Replies: 2
    Last Post: 11-29-2010, 11:59 PM
  2. difference between type conversion and type casting
    By Bargi in forum C Programming
    Replies: 1
    Last Post: 01-23-2007, 03:17 AM
  3. Passing a function pointer to a templated type
    By skorman00 in forum C++ Programming
    Replies: 2
    Last Post: 04-13-2004, 08:31 PM
  4. Replies: 1
    Last Post: 05-18-2003, 05:10 PM
  5. Using a templated object in another class
    By harry_p in forum C++ Programming
    Replies: 3
    Last Post: 08-18-2002, 11:35 PM