So I have a templated vektor class
template<t>
class vektor
{
...
}
and I want to be able to write
vektor<int> x;
vektor<float> y;
...
y = x;
so I modify the class
template<t>
class vektor
{
template<typename U>
vektor<T>& operator=(const vektor<U> &r) {
....
}
...
}
And I'd like this function to be friend with r; that is, I want to be able to access the private members of r. Since operator= is special I can't overload operator= as a non-member function and friend it as I might normally do and friend declarations of say
template<typename U> friend vektor<U>& operator=(const vektor<T> &r);
also return "must be a nonstatic member function"
Is there a way to confer friendship in this example?
There are two quick solutions for this problem (both of them are not ideal).
Suppose that the class with very interesting name vektor looks like this (it is only an example which should illustrate the following code):
template<typename T>
class vektor
{
T data;
public:
vektor(T otherData) :
data(otherData)
{
}
T GetData() const
{
return data;
}
// ...
};
Both of solutions can be tested on the following example of code:
vektor<int> x(1);
vektor<float> y(2.0f);
y = x;
std::cout << "x.data = " << x.GetData() << std::endl;
std::cout << "y.data = " << y.GetData() << std::endl;
First solution: auxiliary friend function template
In this solution an auxiliary friend function Copy is used to execute all copy operations and is called from copy assignment operator:
template<typename T>
class vektor
{
// ...
public:
// ...
template<typename U>
vektor<T>& operator=(const vektor<U>& r)
{
return Copy(*this, r);
}
template<typename V, typename U>
friend vektor<V>& Copy(vektor<V>& l, const vektor<U>& r);
};
template<typename V, typename U>
vektor<V>& Copy(vektor<V>& l, const vektor<U>& r)
{
l.data = static_cast<V>(r.data);
return l;
}
Second solution: friend class template
Second solution is to make all vektor class template instantiations friends to each other:
template<typename T>
class vektor
{
// ...
public:
// ...
template<typename U>
vektor<T>& operator=(const vektor<U>& r)
{
data = static_cast<T>(r.data);
return *this;
}
template<typename U>
friend class vektor;
};
Related
I am very confused about how to get the template argument of the returned object in simple operator overloading.
This is my code:
#include <iostream>
template <typename T>
class numeric {
public:
numeric(): value_{0} {}
numeric(T value): value_{value} {}
numeric(const numeric& other) { value_ = other.value_; }
~numeric() {}
template <typename O>
numeric<T> operator+(const numeric<O>& other) {
return numeric<T>(value_ + other.value_);
}
friend std::ostream& operator<<
(std::ostream& os, const numeric& other) {
os << other.value_;
return os;
}
private:
T value_;
};
int main() {
numeric<int> x = 10;
numeric<float> y = 5.5;
std::cout << (x + y);
return 0;
}
And my desired result was to print out 15.5 on the console.
Even if your attempt didn't have a problem with accessing a private member of another class - which could be worked around by making the member public - you would have a problem with inconsistent behaviour where x + y results in 15 because the type of the result is numeric<int>. y + x would yield the desired 15.5.
You can fix both the access problem, and the return type by using friend operator overload template. Use a template type parameter for both operands. Return wrapper of common type. You'll need to define it outside the class template so that you don't get a different definition for each class template instance:
template <typename T>
class numeric {
...
template<class L, class R>
friend auto operator+(const numeric<L>&, const numeric<R>&);
...
};
template<class L, class R>
auto operator+(const numeric<L>& l, const numeric<R>& r) {
using common_type = numeric<std::common_type_t<L, R>>;
return common_type(l.value_ + r.value_);
}
I've written a class Number that contains only one attribute: T value. I'm currently learning about templates, so T is the data type. What I want to achieve is doing the following sort of computation.
Number<int>(2) + Number<double>(1.2)
What I have so far can do a operation, but it fails when there are two different datatypes. So far I've written this:
//class template
template<class T>
class Number
{
public:
T value;
Number(T num1)
{
value = num1;
}
Number<T> operator + ( const Number<T> &other) const
{
return Number<decltype(value+other.value)> (value+other.value);
}
};
It only does the arithmic operation when the datatypes are the same:
Questions:
Why does the program only work with the same datatypes?
This can I answer for a part by myself. I use the line:
Number<T> operator + ( const Number<T> &other) const
So if the left handside is of type int. Every T becomes an int. I don't know how I need to change it without getting an error.
What do I need to fix in order to do computations with different
datatypes?
Edit:
A constraint is that the template may contain only one type argument
Besides declaring a friend operator+ with two template parameters as suggested, you can also place a secondary template for the member function operator+, which allows you to do casting plus.
template<typename T>
class Number
{
public:
T value;
Number(const T&num1)
{
value = num1;
}
template <typename X> auto operator + ( const Number<X> &other) const
{
auto c = this->value + other.value;
return Number<decltype(c)> ( c );
}
};
#include <iostream>
int main()
{
Number<int> n{2};
Number<double> a{3.4};
std::cout << (a+n).value << std::endl;
}
Or, you may use a friend function (I think that this is more symbolic consistent.)
template<typename T>
class Number
{
public:
T value;
Number(T num1)
{
value = num1;
}
Number& operator +=( const Number<T> &other)
{
this->value += other.value;
return *this;
}
};
template <typename T1,typename T2> auto operator+(const Number<T1>&a, const Number<T2>&b)
{
auto c = a.value + b.value;
return Number<decltype(c)>( c );
}
#include <iostream>
#include <type_traits>
template <typename T>
struct Number {
Number(T _value = T(0)) : value(_value) {}
template <typename S>
Number(const Number<S>& n) : value(n.value) {}
T value;
template <typename S>
friend Number<S> operator+(const Number<S>& a, const Number<S>& b);
};
template <typename S>
Number<S> operator+(const Number<S>& a, const Number<S>& b) {
return Number<S>{a.value + b.value};
}
int main() {
std::cout << operator+<typename std::common_type<int, double>::type>(Number<int>{1}, Number<double>{1.2}).value << std::endl;
return 0;
}
this is a c++11 implementation. operator+ contains exactly one argument. I hope this is what you want.
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;
}
Given the following simple C++ class:
using namespace std;
template<class T1>
class ValueWrapper {
private:
T1 value_;
public:
ValueWrapper() {}
ValueWrapper(const T1& value) {
value_ = value;
}
ValueWrapper(const ValueWrapper<T1> &wrapper) {
value_ = wrapper.value_;
}
ValueWrapper& Set(const T1& value) {
value_ = value;
return *this;
}
T1 Get() const {
return value_;
}
};
I was trying to create a simple shared_ptr wrapper for that class (ultimately allowing the developer to use the class without the dereferencing operator if desired). While I've seen a few examples of wrapping a shared_ptr, I couldn't find any that also used a specialization for a templated class.
Using the class above, I created a ValueShared class which derives from shared_ptr:
template<class T1>
class ValueShared : public shared_ptr<T1> {
public:
ValueShared& operator =(const T1& rhs) {
// nothing to do in base
return *this;
}
};
Then, I created a custom make_shared_value function:
//
// TEMPLATE FUNCTION make_shared
template<class T1, class... Types> inline
ValueShared<T1> make_shared_value(Types&&... Arguments)
{ // make a shared_ptr
_Ref_count_obj<T1> *_Rx = new _Ref_count_obj<T1>(_STD forward<Types>(Arguments)...);
ValueShared<T1> _Ret;
_Ret._Resetp0(_Rx->_Getptr(), _Rx);
return (_Ret);
}
But, here's the problem code:
template<class T1, class ValueWrapper<T1>>
class ValueShared<ValueWrapper<T1>> : public shared_ptr<ValueWrapper<T1>>{
public:
ValueShared& operator =(const ValueWrapper<T1>& rhs) {
auto self = this->get();
self.Set(rhs->Get());
return *this;
}
};
I wanted to provide a specialization of the equals operator here that was specialized to the ValueWrapper class (so that it would Get/Set the value from the right hand side value).
I've tried a few things, but the current error is:
error C2943: 'ValueWrapper<T1>' : template-class-id redefined
as a type argument of a template
Maybe this isn't the proper approach, or maybe it's not possible?
Following should remove your error:
template<class T1>
class ValueShared<ValueWrapper<T1>> : public shared_ptr<ValueWrapper<T1>> {
public:
ValueShared& operator =(const ValueWrapper<T1>& rhs)
{
auto self = this->get();
self->Set(rhs.Get());
return *this;
}
};
Suppose there is the following definition in a header
namespace someNamespace {
template<class T, class S>
int operator + (const T & t, const S & s) {
return specialAdd (t, s);
}
}
Now I would like the user of the header to be able to do something like
using someNamespace::operator + <OneClass,SecondClass>;
which is obviously not possible.
The reason for this is that I do not want my operator + interfere with the standard operator + and therefore give the user the possibility to specify for which types operator + should be defined. Is there a way to achieve this?
Use the barton-nackman trick: http://en.wikipedia.org/wiki/Barton%E2%80%93Nackman_trick
template<typename T,typename S>
class AddEnabled{
friend int operator + (T const& t, const S & s) {
T temp(t);
return temp.add(s);
}
};
class MyClass: public AddEnabled<MyClass,int>{
public:
MyClass(int val):mVal(val){
}
int add(int s){
mVal+=s;
return mVal;
}
private:
int mVal;
};
Here another example to overload the << operator:
template<typename T>
class OutEnabled {
public:
friend std::ostream& operator<<(std::ostream& out, T const& val) {
return static_cast<OutEnabled<T> const&>(val).ioprint(out);
}
protected:
template<typename U>
U& ioprint(U& out) const {
return static_cast<T const*>(this)->print(out);
}
};
To use it you can either let your class inherit from OutEnabled:
class MyClass: public OutEnabled<MyClass>{ ...
or you can define a sentry object e.g. in an anonymous namespace in a cpp file
namespace{
OutEnabled<MyClass> sentry;
}
As soon as the template OutEnabled gets instantiated (OutEnabled<MyClass>) the GLOBAL operator std::ostream& operator<<(std::ostream& out, MyClass const& val)
exists.
Further MyClass must contain a function (template) matching
template<typename U>
U& print(U& out) const {
out << mBottomLeft << "\t"<< mW << "\t"<< mH;
return out;
}
Since this is called by ioprint.
The function U& ioprint(U& out) is not absolutely necessary but it gives you a better error message if you do not have defined print in MyClass.
A type traits class that they can specialize, and enable_if in the operator+? Put the operator+ in the global namespace, but it returns
std::enable_if< for::bar<c1>::value && for::bar<c2>::value, int >
Where bar is a template type traits class in namespace for like this:
template<class T>
struct bar: std::false_type {};
I think that should cause sfinae to make your template plus only match stuff you specialize bar to accept.
You might want to throw some deconst and ref stripping into that enable_if, and do some perfect forwarding in your operator+ as well.