Ciao a tutti. Sto cercando di creare una classe che rappresenta dei vettori matematici.
Volevo chiedere agli esperti se utilizzo la move semantics in modo corretto e in caso contrario dove sbaglio e perché. Inoltre ottengo i warning seguenti per gli operatori friend della classe e non riesco proprio a capire perché.
codice:
In file included from testVector.cc:1:0:
Vector.h:50:51: warning: friend declaration ‘Vector<T> operator*(T, const Vector<T>&)’ declares a non-template function [-Wnon-template-friend]
Vector.h:50:51: note: (if this is not what you intended, make sure the function template has already been declared and add <> after the function name here)
Vector.h:51:51: warning: friend declaration ‘Vector<T> operator*(const Vector<T>&, T)’ declares a non-template function [-Wnon-template-friend]
Vector.h:52:68: warning: friend declaration ‘std::ostream& operator<<(std::ostream&, const Vector<T>&)’ declares a non-template function [-Wnon-template-friend]
g++gcc-4.6.x testVector.o -o testVector
Questo é il mio codice:
codice:
#ifndef VECTOR_H
#define VECTOR_H
#include <vector>
// std::vector
#include <initializer_list>
// std::initializer_list
#include <iostream>
// std::ostream
#include <string>
// std::string
#include <stdexcept>
// std::range_error
#include <algorithm>
// std::copy
// std::equal
#include <iterator>
// std::ostream_iterator
#include <utility>
// std::move
template<typename T = double>
class Vector
{
public:
// --- CONSTRUCTORS ---
Vector(size_t);
Vector(T, T, T);
Vector(const std::vector<T> &);
Vector(const std::initializer_list<T>&);
Vector(const Vector<T>&);
Vector(Vector<T>&&);
// --- DESTRUCTOR ---
virtual ~Vector();
// --- INNER OPERATORS ---
Vector<T>& operator=(const Vector<T>&);
Vector<T>& operator=(const Vector<T>&&);
bool operator==(const Vector<T>&) const;
bool operator!=(const Vector<T>&) const;
Vector<T>& operator+=(const Vector<T>&);
Vector<T>& operator-=(const Vector<T>&);
Vector<T> operator+(const Vector<T>&) const;
Vector<T> operator-(const Vector<T>&) const;
Vector<T> operator-() const;
T operator*(const Vector<T>&) const;
Vector<T> operator^(const Vector<T>&) const;
T operator[](size_t) const;
friend Vector<T> operator*(T, const Vector<T>&);
friend Vector<T> operator*(const Vector<T>&, T);
friend std::ostream& operator<<(std::ostream&, const Vector<T>&);
// --- METHODS ---
size_t size() const;
double norm() const;
protected:
// --- ATTRIBUTES ---
std::vector<T> v;
// --- METHODS ---
void range_except(const Vector<T>&, const std::string&) const;
};
#endif
// *** PUBLIC ***
// --- CONSTRUCTORS ---
// Empty vector
template<typename T>
Vector<T>::Vector(size_t size)
: v(size, 0)
{}
// 3D vector
template<typename T>
Vector<T>::Vector(T x, T y, T z)
: v({x, y, z})
{}
template<typename T>
Vector<T>::Vector(const std::vector<T> & V)
: v(V)
{}
template<typename T>
Vector<T>::Vector(const std::initializer_list<T>& V)
: v(V)
{}
template<typename T>
Vector<T>::Vector(const Vector<T>& V)
: v(V)
{}
template<typename T>
Vector<T>::Vector(Vector<T>&& V)
: v(std::move(V))
{}
// ---DESTRUCTOR ---
template<typename T>
Vector<T>::~Vector()
{}
// --- INNER OPERATORS ---
template<typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>& V)
{
if(&V != this)
{
v = V;
}
return *this;
}
template<typename T>
Vector<T>& Vector<T>::operator=(const Vector<T>&& V)
{
if(&V != this)
{
v = std::move(V);
}
return *this;
}
template<typename T>
bool Vector<T>::operator==(const Vector<T>& V) const
{
if(v.size() == V.size())
{
return equal(v.cbegin(), v.cend(), V.begin());
}
return false;
}
template<typename T>
bool Vector<T>::operator!=(const Vector<T>& V) const
{
return !( (*this) == V);
}
template<typename T>
Vector<T>& Vector<T>::operator+=(const Vector<T>& V)
{
range_except(V, "");
for(int i(0); i < v.size(); i++)
{
v[i] += V.v[i];
}
return *this;
}
template<typename T>
Vector<T>& Vector<T>::operator-=(const Vector<T>& V)
{
range_except(V, "");
for(int i(0); i < v.size(); i++)
{
v[i] -= V.v[i];
}
return *this;
}
template<typename T>
Vector<T> Vector<T>::operator+(const Vector<T>& V) const
{
range_except(V, "");
Vector<T> r(*this);
for(int i(0); i < v.size(); i++)
{
r.v[i] += V.v[i];
}
return std::move(r);
}
template<typename T>
Vector<T> Vector<T>::operator-(const Vector<T>& V) const
{
range_except(V, "");
Vector<T> r(*this);
for(auto i : v)
{
r.v[i] -= V.v[i];
}
return std::move(r);
}
template<typename T>
Vector<T> Vector<T>::operator-() const
{
Vector<T> r(*this);
for (size_t i(0); i < v.size(); i++)
{
r.v[i] = (-1) * r.v[i];
}
return std::move(r);
}
template<typename T>
T Vector<T>::operator*(const Vector<T>& V) const
{
range_except(V, "");
T r(0);
for (size_t i(0); i < v.size(); i++)
{
r += v[i] * V.v[i];
}
return r;
}
template<typename T>
Vector<T> Vector<T>::operator^(const Vector<T>& V) const
{
range_except(V, "");
if (v.size() != 3)
{
throw std::range_error("Cross product works only for 3D vectors");
}
Vector<T> r(v[1] * V.v[2] - v[2] * V.v[1],
v[2] * V.v[0] - v[0] * V.v[2],
v[0] * V.v[1] - v[1] * V.v[0]);
return std::move(r);
}
template<typename T>
T Vector<T>::operator[](size_t i) const
{
return v[i];
}
template<typename T>
Vector<T> operator*(T x, const Vector<T>& V)
{
Vector<T> r(V);
for (size_t i(0); i < r.v.size(); i++)
{
r.v[i] *= x;
}
return std::move(r);
}
template<typename T>
Vector<T> operator*(const Vector<T>& V, T x)
{
Vector<T> r(V);
for (size_t i(0); i < r.v.size(); i++)
{
r.v[i] *= x;
}
return std::move(r);
}
template<typename T>
std::ostream& operator<<(std::ostream& out, const Vector<T>& V)
{
std::copy(V.v.cbegin(), V.v.cend(), std::ostream_iterator<T>(out, " "));
return out;
}
// --- METHODS ---
template<typename T>
size_t Vector<T>::size() const
{
return v.size();
}
template<typename T>
double Vector<T>::norm() const
{
return std::sqrt((*this) * (*this));
}
// *** PRIVATE ***
// --- METHODS ---
template<typename T>
void Vector<T>::range_except(const Vector<T>& V, const std::string& s) const
{
if(v.size() != V.size())
{
throw std::range_error(s);
}
}
Grazie,
R.