0

I'm trying to implement a very basic Vector3 (Vec3) class. I'm struggling with a special case : Vec3<size_t> addition with Vec3<int>.

How can I make a template specialization for this case?

Any help would be appreciated. Ben

#include <array>
#include <ostream>
#include <vector>

// #define Vec3f std::array<float, 3>
// #define Vec3u std::array<size_t, 3>

#define Vec3f Vec3<float>
#define Vec3u Vec3<size_t>
#define Vec3i Vec3<int>

template <typename T>
class Vec3
{
    public:
        Vec3(): _a() {}
        Vec3(T x, T y, T z): _a({x, y, z}) {}
        Vec3(const Vec3<T> & a): _a({a[0], a[1], a[2]}) {}

        ~Vec3() {}

        /// Print Vec3.
        friend std::ostream & operator<<(std::ostream & os, const Vec3<T> & v)
        {
            os << "(" << v[0] << ", " << v[1] << ", " << v[2] << ")";
            return os;
        }

        inline typename std::array<T, 3>::reference operator[](size_t i)
        {
            return _a[i];
        }

        inline typename std::array<T, 3>::const_reference operator[](size_t i) const
        {
            return _a[i];
        }


        /// Test equality.
        inline bool operator==(const Vec3<T> & other) const
        {
            bool a = abs(_a[0] - other._a[0]) < 1e-6;
            bool b = abs(_a[1] - other._a[1]) < 1e-6;
            bool c = abs(_a[2] - other._a[2]) < 1e-6;
            return (a and b and c);
        }

        /// Test non-equality.
        inline bool operator!=(const Vec3<T> & other) const
        {
            return not (*this == other);
        }


        /// Vec3 same type addition.
        inline Vec3<T> operator+(const Vec3<T> & other) const
        {
            return {_a[0] + other[0], _a[1] + other[1], _a[2] + other[2]};
        }


    protected:
        std::array<T, 3> _a;
};
David G
  • 94,763
  • 41
  • 167
  • 253
  • 2
    What is exactly your problem? – Petr Jun 29 '15 at 14:57
  • As an FYI you don't need to use inline on all of your functions. see: [Is “inline” implicit in C++ member functions defined in class definition](http://stackoverflow.com/questions/9192077/is-inline-implicit-in-c-member-functions-defined-in-class-definition) – NathanOliver Jun 29 '15 at 15:11
  • @NathanOliver. Thanks for the tip. –  Jun 29 '15 at 18:24

1 Answers1

3

Your problem is to find the common type between size_t and int that is the template argument for the result. This is a possible solution:

/// Vec3 addition between vectors of different base type.
template <class U>
Vec3<typename std::common_type<T, U>::type> operator+(const Vec3<U> & other) const
{
    return{ _a[0] + other[0], _a[1] + other[1], _a[2] + other[2] };
}
marom
  • 5,064
  • 10
  • 14
  • Depending of expected result `Vec3() + declval())>` may be used instead of `common_type` (`char + char` is `int`, but its common type is `char`) – Jarod42 Jun 29 '15 at 17:04
  • @Jarod42: thanks for the comment, it's a point of view I missed. But I have found some contexts in which the rule char+char->int was ok, since it prevented overflows (context was RGB pixels, the problem was that the int based pixel had,sooner or later, to be converted somehow back to char version) – marom Jun 29 '15 at 18:29
  • Thank you both for your help. Unfortunately, this is not as restrictive as I would like. I'd like a function **specifically** to add `Vec3` and `Vec3`. Both your solutions are too permissive as they implement `Vec3` and `Vec3` addition too, for instance. –  Jun 30 '15 at 09:50