Redefining Friend Function of Base Class in Derived Class - c++

I want to redefine the operator* function that is originally defined as a friend in the Vector class, in a derived class, BigNum. Specifically I want to call the Vector version of operator* and then do some other things to the result of that operation in BigNum's operator*. Here's a snippet of the structure (thanks again to #lemmes for helping with this):
template<typename T>
class Vector
{
private:
std::vector<T> base;
public:
Vector();
Vector(const std::vector<T> vec);
Vector(const Vector& vec);
template<typename T1, typename T2>
friend auto operator*(const Vector<T1>& lhs, const Vector<T2>& rhs) -> Vector<decltype(std::declval<T1>() * std::declval<T2>())>;
};
template<typename T1, typename T2>
auto operator*(const Vector<T1>& lhs, const Vector<T2>& rhs) -> Vector<decltype(std::declval<T1>() * std::declval<T2>())>
{
typedef decltype(std::declval<T1>() * std::declval<T2>()) T3;
assert(lhs.base.size() == rhs.base.size());
Vector<T3> result;
result.base.reserve(lhs.base.size());
std::transform(lhs.base.begin(), lhs.base.end(), rhs.base.begin(), std::back_inserter(result.base),
[](const T1& e1, const T2& e2) { return e1 * e2; });
return result;
}
class BigNum : public Vector<int>
{
public:
BigNum();
BigNum(const std::vector<int> init);
~BigNum();
BigNum operator*(const BigNum& rhs);
};
#endif
BigNum BigNum::operator*(const BigNum& rhs)
{
// How can I call Vector's operator* (a friend of the Vector class)
// and then do other stuff in here?
}
#include "BigNum.h"
int main()
{
int arr1[] = {1,2,3,4,5};
int arr2[] = {10,20,30,40,50};
std::vector<int> vec1 (arr1, arr1 + sizeof(arr1) / sizeof(arr1[0]));
std::vector<int> vec2 (arr2, arr2 + sizeof(arr2) / sizeof(arr2[0]));
BigNum bn1(vec1), bn2(vec2);
bn1 * bn2; // want to call BigNum's operator* here
return 0;
}
I obviously can't do something like Vector::operator* since it's a friend. Thanks in advance!

You can write static_cast<Vector<int>&>(bn1) * static_cast<Vector<int>&>(bn2) to have the vector's overloaded operator called.

Related

Using friend operator overload function in template class, error undefined reference

Here is my code and declarations, im not sure how to properly set up friend functions with template classes. Can someone please guide me on what I did wrong and why?
Thanks!
private:
int size;
T* buff;
friend Vector<T> operator * (const int n, const Vector<T> & v);
friend Vector<T> operator + (const int n, const Vector<T> & v);
template<typename T>
Vector<T> operator * (const int n, const Vector<T> & v){
Vector<T> vec(v.size);
vec.size = v.size;
for(int i = 0;i<vec.size;i++){
vec.buff[i] = v.buff[i]*n;
}
}
template<typename T>
Vector<T> operator+ (const int n, const Vector<T> & v){
Vector<T> vec(v.size);
vec.size = v.size;
for(int i = 0;i<vec.size;i++){
vec.buff[i] = v.buff[i]*n;
}
}

C++ template class friend with all type

I have a Vector class and I overload the operator*
I would like to be able to multiply a Vector of float with a Vector of int.
I have the following code but when I compile him, I have an error because I don't have access to private fields.
template <class T>
class Vecteur
{
template <class U> friend class Vecteur;
private:
int m_dimensions;
T *m_values;
}
template<class T1, class T2>
T1 operator*(const Vecteur<T1> &v1, const Vecteur<T2> &v2)
{
assert(v1.m_dimensions == v2.m_dimensions);
T res = T();
for (int i = 0; i < v1.m_dimensions; i++)
{
res += v1.m_values[i] * v2.m_values[i];
}
return res;
}
I also tried this but I can access to private fields of v1 but not to the private fields of v2
template <class T>
class Vecteur
{
private:
int m_dimensions;
T *m_values;
template<class T2>
friend T operator*(const Vecteur<T> &v1, const Vecteur<T2> &v2)
{
assert(v1.m_dimensions == v2.m_dimensions);
T res = T();
for (int i = 0; i < v1.m_dimensions; i++)
{
res += v1.m_values[i] * v2.m_values[i];
}
return res;
}
}
Your first version declares one specialization of Vecteur a friend of another. This doesn't help your operator *, since this is still not a friend and can't access private members.
Add proper friend declaration for template overload in your Vecteur (and you do not need to friend the specialization):
template<class T>
class Vectuer {
//...
template<class T1, class T2> std::common_type_t<T1, T2>
friend operator*(const Vecteur<T1>& , const Vectuer<T2>& );
//...
};
// And than a definition after the declaration
Alternatively, you can friend the specialization, and add operator* as a member, but I do not like this, since such overloaded operators are more cleanly implemented as freestanding functions.
When you have the urge to declare a function or a class a friend of a class, take moment to look at your design and ask yourself whether that is absolutely necessary.
In the case of the posted code, instead of trying to solve the problem associated with granting friend-ship to the operator* function, provide accessor functions to the data of the class and get rid of the need for granting friend-ship altogether.
template <class T>
class Vecteur
{
public:
int getDimensions() const { return m_dimensions; };
T& operator[](std::size_t i) { return m_values[i]; };
T const& operator[](std::size_t i) const { return m_values[i]; };
private:
int m_dimensions;
T *m_values;
};
// Does not require to be a friend of the class.
template<class T1, class T2>
typename std::common_type<T1, T2>::type operator*(const Vecteur<T1> &v1, const Vecteur<T2> &v2)
{
assert(v1.getDimensions() == v2.getDimensions());
typename std::common_type<T1, T2>::type res{};
for (int i = 0; i < v1.getDimensions(); i++)
{
res += v1[i] * v2[i];
}
return res;
}

commutative operators in a template class with an invariant return type

I have a fairly simple template class as follows. It is essentially an extension on the std::shared_ptr in C++11 where I would like to overload various operators. For this question the multiplication operator*(), and I would like it to be commutative.
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
assert(Variable != 0x0);
return (*Variable);
}
template < typename U >
friend T operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
}
The issue with this implementation is when I utilize this PoolVar class with my Vector and Quaternion classes defined as follows. Both of which define the multiplication operator such that it is commutative to any user of the classes.
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
}
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
}
What I want is for the PoolVar overloaded operator to essentially just be a pass through for any data type, such that I can do something like the following. Assume I allocated and initialized the Variable in the PoolVar objects correctly.
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q; // works currently
Vector v2 = q*v; // does not
Quaternion q1 = q*q; // ambiguous
The moment I attempt to add another friend operator as follows to PoolVar to achieve the pattern that does not work above, I get a bunch of error messages at compile time for ambiguous operators as marked above.
template < typename U >
friend T operator*(const PoolVar<U> & lhs, const PoolVar<T> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
The only thing I have found to work is to explicitly define the various combinations of the operators outside the PoolVar class, such as:
inline Vector operator*(PoolVar<Vector> & lhs, PoolVar<Quaternion> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
inline Vector operator*(PoolVar<Quaternion> & lhs, PoolVar<Vector> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
I really do not want to do this, if I can at all help it, because it is a serious limitation on the PoolVar class and would increase the maintenance of the code-base for any new special class like Vector and Quaternion.
The issue is not so much that I can create a commutative operator (I think) as it is that the return type for both definitions is the same (invariant), which leads to ambiguous overloading unless explicitly defined.
Is there any way to set up a template class to have commutative operators with invariant return types, such as this multiplication operator? Also, I should note that I do not have the luxury of utilizing C++11, if that perchance would have helped.
I'm not 100% sure, since I haven't tried out all the new C++11 features but it seems like this could be solved with trailing return type thus allowing the compiler to deduce the return type. I put together an example from your snippets:
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
template <typename U>
friend auto operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) -> decltype(lhs * rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
};
class Quaternion;
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
};
int main(int argc, char** argv)
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q;
Vector v2 = q*v;
return 0;
}
Since I'm on Windows and Visual Studio 2012 does not seem to support this I tried to compile it with gcc on Ubuntu VM and on http://gcc.godbolt.org/ but in both cases the compilers crash. Can anyone hint if this is an appropriate/inappropriate use of trailing return types in context of this question?
EDIT
I understood what was bad with the initial example, it introduces in infinitely deep recursion since the evaluation of the multiplication operator will yield evaluation of the same template. However when I tried:
template <typename U>
friend auto operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) -> decltype(lhs.GetValue() * rhs.GetValue()) {
return (lhs.GetValue() * rhs.GetValue());
}
which gave errors about accessing incomplete type PoolVar, so I moved the operator outside of the class scope:
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
};
template <typename T, typename U>
auto operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) -> decltype(lhs.GetValue() * rhs.GetValue()) {
return (lhs.GetValue() * rhs.GetValue());
}
class Quaternion;
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
};
int main(int argc, char** argv)
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q;
Vector v2 = q*v;
return 0;
}
This seemed to compile fine, so I guess my initial idea was right, thanks for the great question, so far I did not have a good example to try the trailing return types on.
EDIT 2
GCC has a built in extension called typeof that can solve this without C++11, but then again it is GCC specific:
template<typename T, typename U>
class EvaluateResult
{
static T m_a;
static U m_b;
public:
typedef typeof(m_a * m_b) Result;
};
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
};
template <typename T, typename U>
typename EvaluateResult<T,U>::Result operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
class Quaternion;
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const;
};
int main(int argc, char** argv)
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
/* Stuff to create and initialize correctly. */
Vector v1 = v*q;
Vector v2 = q*v;
}
template<typename T>
class PoolVar {
private:
T * Variable;
public:
T GetValue() const {
return (*Variable);
}
template < typename U >
friend typename T::type operator*(const PoolVar<T> & lhs, const PoolVar<U> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
// to handle equl types :)
friend T operator*(const PoolVar<T> & lhs, const PoolVar<T> & rhs) {
return (lhs.GetValue() * rhs.GetValue());
}
};
class Vector {
public:
friend class Quaternion;
protected:
double V_Value[3];
public:
Vector operator*(const Quaternion & q) const{ return Vector(); }
Vector operator*(const Vector & q) const{ return Vector(); }
typedef Vector type;
};
class Quaternion {
public:
friend class Vector;
protected:
double Q_Scalar;
Vector Q_Vector;
public:
Vector operator*(const Vector & v) const {return Vector();};
Quaternion operator*(const Quaternion & v) const {return Quaternion();};
typedef Vector type;
};
int main()
{
PoolVar<Vector> v;
PoolVar<Quaternion> q;
Vector v1 = v * q; // good
Vector v2 = q * v; // good
Quaternion qq = q * q; // good
Vector vv = v * v; // good
return 0;
}
try this

Sorting a pair of vectors

I know how to sort a vector of pairs, but how do you sort a pair of vectors? I can think of writing a custom "virtual" iterator over a pair of vectors and sorting that, but that seems quite complex. Is there an easier way? Is there one in C++03? I would like to use std::sort.
This problem arises when processing some data generated in hardware, where a pair of arrays makes more sense than array of pairs (since then there would be all kinds of stride and alignment problems). I realize that otherwise keeping a pair of vector instead of a vector of pairs would be a design flaw (the structure of arrays problem). I'm looking for a fast solution, copying the data to a vector of pairs and then back (I will return it to the HW to do more processing) is not an option.
Example:
keys = {5, 2, 3, 1, 4}
values = {a, b, d, e, c}
and after sorting (by the first vector):
keys = {1, 2, 3, 4, 5}
values = {e, b, d, c, a}
I refer to a "pair of vectors" as the pair of keys and values (stored as e.g. std::pair<std::vector<size_t>, std::vector<double> >). The vectors have the same length.
Let's make a sort/permute iterator, so that we can just say:
int keys[] = { 5, 2, 3, 1, 4 };
char vals[] = { 'a', 'b', 'd', 'e', 'c' };
std::sort(make_dual_iter(begin(keys), begin(vals)),
make_dual_iter(end(keys), end(vals)));
// output
std::copy(begin(keys), end(keys), std::ostream_iterator<int> (std::cout << "\nKeys:\t", "\t"));
std::copy(begin(vals), end(vals), std::ostream_iterator<char>(std::cout << "\nValues:\t", "\t"));
See it Live On Coliru, printing
Keys: 1 2 3 4 5
Values: e b d c a
Based on the idea here, I've implemented this:
namespace detail {
template <class KI, class VI> struct helper {
using value_type = boost::tuple<typename std::iterator_traits<KI>::value_type, typename std::iterator_traits<VI>::value_type>;
using ref_type = boost::tuple<typename std::iterator_traits<KI>::reference, typename std::iterator_traits<VI>::reference>;
using difference_type = typename std::iterator_traits<KI>::difference_type;
};
}
template <typename KI, typename VI, typename H = typename detail::helper<KI, VI> >
class dual_iter : public boost::iterator_facade<dual_iter<KI, VI>, // CRTP
typename H::value_type, std::random_access_iterator_tag, typename H::ref_type, typename H::difference_type>
{
public:
dual_iter() = default;
dual_iter(KI ki, VI vi) : _ki(ki), _vi(vi) { }
KI _ki;
VI _vi;
private:
friend class boost::iterator_core_access;
void increment() { ++_ki; ++_vi; }
void decrement() { --_ki; --_vi; }
bool equal(dual_iter const& other) const { return (_ki == other._ki); }
typename detail::helper<KI, VI>::ref_type dereference() const {
return (typename detail::helper<KI, VI>::ref_type(*_ki, *_vi));
}
void advance(typename H::difference_type n) { _ki += n; _vi += n; }
typename H::difference_type distance_to(dual_iter const& other) const { return ( other._ki - _ki); }
};
Now the factory function is simply:
template <class KI, class VI>
dual_iter<KI, VI> make_dual_iter(KI ki, VI vi) { return {ki, vi}; }
Note I've been a little lazy by using boost/tuples/tuple_comparison.hpp for the sorting. This could pose a problem with stable sort when multiple key values share the same value. However, in this case it's hard to define what is "stable" sort anyways, so I didn't think it important for now.
FULL LISTING
Live On Coliru
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/tuple/tuple_comparison.hpp>
namespace boost { namespace tuples {
// MSVC might not require this
template <typename T, typename U>
inline void swap(boost::tuple<T&, U&> a, boost::tuple<T&, U&> b) noexcept {
using std::swap;
swap(boost::get<0>(a), boost::get<0>(b));
swap(boost::get<1>(a), boost::get<1>(b));
}
} }
namespace detail {
template <class KI, class VI> struct helper {
using value_type = boost::tuple<typename std::iterator_traits<KI>::value_type, typename std::iterator_traits<VI>::value_type>;
using ref_type = boost::tuple<typename std::iterator_traits<KI>::reference, typename std::iterator_traits<VI>::reference>;
using difference_type = typename std::iterator_traits<KI>::difference_type;
};
}
template <typename KI, typename VI, typename H = typename detail::helper<KI, VI> >
class dual_iter : public boost::iterator_facade<dual_iter<KI, VI>, // CRTP
typename H::value_type, std::random_access_iterator_tag, typename H::ref_type, typename H::difference_type>
{
public:
dual_iter() = default;
dual_iter(KI ki, VI vi) : _ki(ki), _vi(vi) { }
KI _ki;
VI _vi;
private:
friend class boost::iterator_core_access;
void increment() { ++_ki; ++_vi; }
void decrement() { --_ki; --_vi; }
bool equal(dual_iter const& other) const { return (_ki == other._ki); }
typename detail::helper<KI, VI>::ref_type dereference() const {
return (typename detail::helper<KI, VI>::ref_type(*_ki, *_vi));
}
void advance(typename H::difference_type n) { _ki += n; _vi += n; }
typename H::difference_type distance_to(dual_iter const& other) const { return ( other._ki - _ki); }
};
template <class KI, class VI>
dual_iter<KI, VI> make_dual_iter(KI ki, VI vi) { return {ki, vi}; }
#include <iostream>
using std::begin;
using std::end;
int main()
{
int keys[] = { 5, 2, 3, 1, 4 };
char vals[] = { 'a', 'b', 'd', 'e', 'c' };
std::sort(make_dual_iter(begin(keys), begin(vals)),
make_dual_iter(end(keys), end(vals)));
std::copy(begin(keys), end(keys), std::ostream_iterator<int> (std::cout << "\nKeys:\t", "\t"));
std::copy(begin(vals), end(vals), std::ostream_iterator<char>(std::cout << "\nValues:\t", "\t"));
}
Just for comparison, this is how much code the split iterator approach requires:
template <class V0, class V1>
class CRefPair { // overrides copy semantics of std::pair
protected:
V0 &m_v0;
V1 &m_v1;
public:
CRefPair(V0 &v0, V1 &v1)
:m_v0(v0), m_v1(v1)
{}
void swap(CRefPair &other)
{
std::swap(m_v0, other.m_v0);
std::swap(m_v1, other.m_v1);
}
operator std::pair<V0, V1>() const // both g++ and msvc sort requires this (to get a pivot)
{
return std::pair<V0, V1>(m_v0, m_v1);
}
CRefPair &operator =(std::pair<V0, V1> v) // both g++ and msvc sort requires this (for insertion sort)
{
m_v0 = v.first;
m_v1 = v.second;
return *this;
}
CRefPair &operator =(const CRefPair &other) // required by g++ (for _GLIBCXX_MOVE)
{
m_v0 = other.m_v0;
m_v1 = other.m_v1;
return *this;
}
};
template <class V0, class V1>
inline bool operator <(std::pair<V0, V1> a, CRefPair<V0, V1> b) // required by both g++ and msvc
{
return a < std::pair<V0, V1>(b); // default pairwise lexicographical comparison
}
template <class V0, class V1>
inline bool operator <(CRefPair<V0, V1> a, std::pair<V0, V1> b) // required by both g++ and msvc
{
return std::pair<V0, V1>(a) < b; // default pairwise lexicographical comparison
}
template <class V0, class V1>
inline bool operator <(CRefPair<V0, V1> a, CRefPair<V0, V1> b) // required by both g++ and msvc
{
return std::pair<V0, V1>(a) < std::pair<V0, V1>(b); // default pairwise lexicographical comparison
}
namespace std {
template <class V0, class V1>
inline void swap(CRefPair<V0, V1> &a, CRefPair<V0, V1> &b)
{
a.swap(b);
}
} // ~std
template <class It0, class It1>
class CPairIterator : public std::random_access_iterator_tag {
public:
typedef typename std::iterator_traits<It0>::value_type value_type0;
typedef typename std::iterator_traits<It1>::value_type value_type1;
typedef std::pair<value_type0, value_type1> value_type;
typedef typename std::iterator_traits<It0>::difference_type difference_type;
typedef /*typename std::iterator_traits<It0>::distance_type*/difference_type distance_type; // no distance_type in g++, only in msvc
typedef typename std::iterator_traits<It0>::iterator_category iterator_category;
typedef CRefPair<value_type0, value_type1> reference;
typedef reference *pointer; // not so sure about this, probably can't be implemented in a meaningful way, won't be able to overload ->
// keep the iterator traits happy
protected:
It0 m_it0;
It1 m_it1;
public:
CPairIterator(const CPairIterator &r_other)
:m_it0(r_other.m_it0), m_it1(r_other.m_it1)
{}
CPairIterator(It0 it0 = It0(), It1 it1 = It1())
:m_it0(it0), m_it1(it1)
{}
reference operator *()
{
return reference(*m_it0, *m_it1);
}
value_type operator *() const
{
return value_type(*m_it0, *m_it1);
}
difference_type operator -(const CPairIterator &other) const
{
assert(m_it0 - other.m_it0 == m_it1 - other.m_it1);
// the iterators always need to have the same position
// (incomplete check but the best we can do without having also begin / end in either vector)
return m_it0 - other.m_it0;
}
bool operator ==(const CPairIterator &other) const
{
assert(m_it0 - other.m_it0 == m_it1 - other.m_it1);
return m_it0 == other.m_it0;
}
bool operator !=(const CPairIterator &other) const
{
return !(*this == other);
}
bool operator <(const CPairIterator &other) const
{
assert(m_it0 - other.m_it0 == m_it1 - other.m_it1);
return m_it0 < other.m_it0;
}
bool operator >=(const CPairIterator &other) const
{
return !(*this < other);
}
bool operator <=(const CPairIterator &other) const
{
return !(other < *this);
}
bool operator >(const CPairIterator &other) const
{
return other < *this;
}
CPairIterator operator +(distance_type d) const
{
return CPairIterator(m_it0 + d, m_it1 + d);
}
CPairIterator operator -(distance_type d) const
{
return *this + -d;
}
CPairIterator &operator +=(distance_type d)
{
return *this = *this + d;
}
CPairIterator &operator -=(distance_type d)
{
return *this = *this + -d;
}
CPairIterator &operator ++()
{
return *this += 1;
}
CPairIterator &operator --()
{
return *this += -1;
}
CPairIterator operator ++(int) // msvc sort actually needs this, g++ does not
{
CPairIterator old = *this;
++ (*this);
return old;
}
CPairIterator operator --(int)
{
CPairIterator old = *this;
-- (*this);
return old;
}
};
template <class It0, class It1>
inline CPairIterator<It0, It1> make_pair_iterator(It0 it0, It1 it1)
{
return CPairIterator<It0, It1>(it0, it1);
}
It is kind of rough around the edges, maybe I'm just bad at overloading the comparisons, but the amount of differences needed to support different implementations of std::sort makes me think the hackish solution might actually be more portable. But the sorting is much nicer:
struct CompareByFirst {
bool operator ()(std::pair<size_t, char> a, std::pair<size_t, char> b) const
{
return a.first < b.first;
}
};
std::vector<char> vv; // filled by values
std::vector<size_t> kv; // filled by keys
std::sort(make_pair_iterator(kv.begin(), vv.begin()),
make_pair_iterator(kv.end(), vv.end()), CompareByFirst());
// nice
And of course it gives the correct result.
Inspired by a comment by Mark Ransom, this is a horrible hack, and an example of how not to do it. I only wrote it for amusement and because I was wondering how complicated would it get. This is not an answer to my question, I will not use this. I just wanted to share a bizarre idea. Please, do not downvote.
Actually, ignoring multithreading, I believe this could be done:
template <class KeyType, class ValueVectorType>
struct MyKeyWrapper { // all is public to save getters
KeyType k;
bool operator <(const MyKeyWrapper &other) const { return k < other.k; }
};
template <class KeyType, class ValueVectorType>
struct ValueVectorSingleton { // all is public to save getters, but kv and vv should be only accessible by getters
static std::vector<MyKeyWrapper<KeyType, ValueVectorType> > *kv;
static ValueVectorType *vv;
static void StartSort(std::vector<MyKeyWrapper<KeyType, ValueVectorType> > &_kv, ValueVectorType &_vv)
{
assert(!kv && !vv); // can't sort two at once (if multithreading)
assert(_kv.size() == _vv.size());
kv = &_kv, vv = &_vv; // not an attempt of an atomic operation
}
static void EndSort()
{
kv = 0, vv = 0; // not an attempt of an atomic operation
}
};
template <class KeyType, class ValueVectorType>
std::vector<MyKeyWrapper<KeyType, ValueVectorType> >
*ValueVectorSingleton<KeyType, ValueVectorType>::kv = 0;
template <class KeyType, class ValueVectorType>
ValueVectorType *ValueVectorSingleton<KeyType, ValueVectorType>::vv = 0;
namespace std {
template <class KeyType, class ValueVectorType>
void swap(MyKeyWrapper<KeyType, ValueVectorType> &a,
MyKeyWrapper<KeyType, ValueVectorType> &b)
{
assert((ValueVectorSingleton<KeyType, ValueVectorType>::vv &&
ValueVectorSingleton<KeyType, ValueVectorType>::kv)); // if this triggers, someone forgot to call StartSort()
ValueVectorType &vv = *ValueVectorSingleton<KeyType, ValueVectorType>::vv;
std::vector<MyKeyWrapper<KeyType, ValueVectorType> > &kv =
*ValueVectorSingleton<KeyType, ValueVectorType>::kv;
size_t ai = &kv.front() - &a, bi = &kv.front() - &b; // get indices in key vector
std::swap(a, b); // swap keys
std::swap(vv[ai], vv[bi]); // and any associated values
}
} // ~std
And sorting as:
std::vector<char> vv; // filled by values
std::vector<MyKeyWrapper<size_t, std::vector<char> > > kv; // filled by keys, casted to MyKeyWrapper
ValueVectorSingleton<size_t, std::vector<char> >::StartSort(kv, vv);
std::sort(kv.begin(), kv.end());
ValueVectorSingleton<size_t, std::vector<char> >::EndSort();
// trick std::sort into using the custom std::swap which also swaps the other vectors
This is obviously very appalling, trivial to abuse in horrible ways, but arguably much shorter than the pair of iterators and probably similar in performance. And it actually works.
Note that swap() could be implemented inside ValueVectorSingleton and the one injected in the std namespace would just call it. That would avoid having to make vv and kv public. Also, the addresses of a and b could further be checked to make sure they are inside kv and not some other vector. Also, this is limited to sorting by values of only one vector (can't sort by corresponding values in both vectors at the same time). And the template parameters could be simply KeyType and ValueType, this was written in a hurry.
Here is a solution I once used to sort an array together with an array of indices (--maybe it is from somewhere over here?):
template <class iterator>
class IndexComparison
{
public:
IndexComparison (iterator const& _begin, iterator const& _end) :
begin (_begin),
end (_end)
{}
bool operator()(size_t a, size_t b) const
{
return *std::next(begin,a) < *std::next(begin,b);
}
private:
const iterator begin;
const iterator end;
};
Usage:
std::vector<int> values{5,2,5,1,9};
std::vector<size_t> indices(values.size());
std::iota(indices.begin(),indices.end(),0);
std::sort(indices.begin(),indices.end()
, IndexComparison<decltype(values.cbegin())>(values.cbegin(),values.cend()));
Afterwards, the integers in vector indices are permuted such that they correspond to increasing values in the vector values. It is easy to extend this from less-comparison to general comparison functions.
Next, in order to sort also the values, you can do another
std::sort(values.begin(),values.end());
using the same comparison function. This is the solution for the lazy ones. Of course, you can alternatively also use the sorted indices according to
auto temp=values;
for(size_t i=0;i<indices.size();++i)
{
values[i]=temp[indices[i]];
}
DEMO
EDIT: I just realized that the above sorts into the opposite direction than the one you were asking for.

Operator Overload for Template Class Auto Type Conversion

I have a template class for which I'm overloading operator+, but need it to potentially return a different data type than what the class is instantiated for. For example, the following snippet performs the standard mathematical definition of either vector*vector (inner product), vector*scalar, or scalar*vector. To be specific, let's say I have a Vector<int> and the scalar is of type double -- I want to return a double from the "vector*scalar" operator+ function.
I'm pretty sure I'm missing some template<class T> statements for the friend functions(?), but this snippet isn't meant to compile.
template<class T>
class Vector
{
private:
std::vector<T> base;
public:
friend Vector operator*(const Vector& lhs, const Vector& rhs); // inner product
Vector<T> operator*(const T scalar); // vector*scalar
friend Vector operator*(const T scalar, const Vector& rhs); // scalar*vector
};
template<class T>
Vector<T> operator*(const Vector<T>& lhs, const Vector<T>& rhs) // inner product
{
assert( lhs.base.size() == rhs.base.size() );
Vector result;
result.base.reserve(lhs.base.size());
std::transform( lhs.base.begin(), lhs.base.end(), rhs.base.begin(), std::back_inserter(result.base), std::multiplies<T>() );
return result;
}
template<class T>
Vector<T> Vector<T>::operator*(const T scalar) // vector*scalar
{
Vector result;
result.base.reserve(base.size());
std::transform( base.begin(), base.end(), std::back_inserter(result.base), std::bind1st(std::multiplies<T>(), scalar) );
return result;
}
template<class T>
Vector<T> operator*(const T scalar, const Vector<T>& rhs) // scalar*vector
{
Vector result;
result.base.reserve(rhs.base.size());
std::transform( rhs.base.begin(), rhs.base.end(), std::back_inserter(result.base), std::bind1st(std::multiplies<T>(), scalar) );
return result;
}
I guess what you want is to return a Vector with the value type being the type returned by the per-component operation, which is not necessarily the type of the scalar.
For example:
Vector<int> * int -> Vector<int>
Vector<int> * double -> Vector<double>
Vector<double> * int -> Vector<double>
Vector<char> * float -> Vector<float>
etc.
For this, you should define the two input types separately, let's say T1 and T2 (and one or two of the operands is a Vector of it). You don't want to simply use the scalar type (for vector * scalar, or scalar * vector operation) as the result, otherwise it might be converted (see my 3rd example: The result would then be Vector<int>.
The above can be done using decltype to find the third (result) type.
For simplicity, define the operator as a non-member:
template<typename T1, typename T2, typename T3 = decltype(std::declval<T1>() * std::declval<T2>())>
Vector<T3> operator*(const Vector<T1>& lhs, const T2 & scalar) // inner product
{
Vector<T3> result;
//...
return result;
}
The interesting part is
T3 = decltype(std::declval<T1>() * std::declval<T2>())
Here, we find the type T3 using the other two types T1 and T2. First, we construct two values with unimportant value (the std::declval function is a helper function returning the type given as a template parameter). Then we multiply those values, but again the result is unimportant; we're only interested in the type. That's what the third part does: decltype gives you the type of the expression (without evaluating it).
The other operators can be implemented analogous.
In order to make those operators friends, you need the syntax
template<...> friend ...
as seen in Danvil's answer.
The friend declaration should look like this:
template<class S>
class Vector
{
private:
std::vector<S> base;
public:
template<class T> friend T operator*(const Vector<T>& lhs, const Vector<T>& rhs); // inner product
template<class T> friend Vector<T> operator*(const T scalar); // vector*scalar
template<class T> friend Vector<T> operator*(const T scalar, const Vector<T>& rhs); // scalar*vector
};
And the rest of the code like this:
template<class T>
T operator*(const Vector<T>& lhs, const Vector<T>& rhs) // inner product
{
assert( lhs.base.size() == rhs.base.size() );
Vector<T> result;
result.base.reserve(lhs.base.size());
std::transform( lhs.base.begin(), lhs.base.end(), rhs.base.begin(), std::back_inserter(result.base), std::multiplies<T>() );
return result;
}
template<class T>
Vector<T> operator*(const Vector<T>& lhs, const T scalar) // vector*scalar
{
return scalar*lhs;
}
template<class T>
Vector<T> operator*(const T scalar, const Vector<T>& rhs) // scalar*vector
{
Vector<T> result;
result.base.reserve(rhs.base.size());
std::transform( rhs.base.begin(), rhs.base.end(), std::back_inserter(result.base), std::bind1st(std::multiplies<T>(), scalar) );
return result;
}
You can add more template parameters as such:
template<class T, class S>
Vector<S> Vector<T>::operator*(const S scalar)
and make sure you use S for the scalar type and T for the vector element type in the correct places in the function body.