0

I have created a Vector class that takes the number of elements and the element type as template arguments.

template<int n, class T>
class Vector
{
    public:
        T data[n];

        Vector()
        : data{}
        {
        }

        Vector(T const value)
        {
            std::fill_n(data, n, value);
        }

        template<class ...U, typename std::enable_if<sizeof...(U) == n, int>::type = 0>
        Vector(U &&...u)
        : data{std::forward<U>(u)...}
        {
        }

        T& operator[](int const index)
        {
            return data[index];
        }

        template<class U>
        operator Vector<n, U>()
        {
            Vector<n, U> out;

            std::copy_n(data, n, out.data);

            return out;
        } 
};

I want to have operators for the class, but in order for them to do conversions between vectors with different element types they need to be friend functions declared and defined inside the class body. But I also want to have 3 specialized template classes for Vector 2, 3, and 4. Since I do not want to have to write all the operators 4 times, once inside each class body. Could I just use this operator with an additional template argument for the element type of the right hand side vector?

template<int n, class T, class U>
inline Vector<n, T>& operator+=(Vector<n, T> &lhs, Vector<n, U> const &rhs)
{
    for(int i = 0; i < n; ++i)
    {
        lhs.data[i] += rhs.data[i];
    }

    return lhs;
}

There is probably a reason that people use friend operators inside the class instead of doing it this way, but it seems fine so far, have I overlooked something?

Thomas Hiatt
  • 63
  • 1
  • 3

1 Answers1

0

There's nothing here beyond the sum of the parts. "friend" is used to grant access to non-public members operators might want to use, and putting the definition inside the class saves on typing (and implicitly makes them inline, avoid One Definition Rule issues). If you're throwing together a class, you can start typing a "friend ..." operator definition without even slowing down to think about whether it needs to be a friend. Some people may also like having the operators listed inside the class - it does make it easier to ensure they're seen when someone looks over the class to see what functions are available - but programmers normally get used to looking for operators after a class anyway....

If your code works, all's good.

Tony Delroy
  • 102,968
  • 15
  • 177
  • 252
  • 'friend' does more than that. My question is similar to http://stackoverflow.com/questions/8890051/implicit-conversion-when-overloading-operators-for-template-classes . The operator function needs to be able to add a vector of floats and a vector of ints together. But the template argument deduction happens before implicit type conversions. Rather than use the solution from that question I have created this work-around. I am wondering if my workaround will cause any issues that would not occur if I used the solution from that question. – Thomas Hiatt Jan 04 '14 at 16:26
  • That answer does not illustrate the need for friend you talk about - for example, with the value member made public, and a two-parameter template covering the general addition case, the following code works just fine: http://ideone.com/0hMp83 - this is the obvious way to do it, and indeed - isn't it what you're asking about in your question? - I wouldn't call it a "workaround". – Tony Delroy Jan 04 '14 at 17:58
  • Further - that answer has a template with `template foo(const foo& that) : _value(that.getval()) {}` - it's forcing a painful implicit construction of an extra Vector before the `+` operator kicks in. You're better off with the code in your answer. – Tony Delroy Jan 04 '14 at 18:07