Can't access global Swap function within from a class - c++

this is my first question on the site.
A little problem met me today. I can't call a global function Swap within a assignment operator and move constructor from the DynamicArray template class. When I try to do this I get an error C2660 saying:
'DynamicArray<int>::Swap' : function does not take 2 arguments.
It's strange for me, because I can call this function with 2 arguments in main function. Does anyone know what is the reason of that?
#include <iostream>
#include <stdexcept>
using std::cout;
using std::cin;
using std::endl;
template <typename T>
class DynamicArray;
template <typename T>
inline void Swap(DynamicArray<T>& lhs, DynamicArray<T>& rhs) {
lhs.Swap(rhs);
}
template <typename T>
class DynamicArray {
public:
DynamicArray(size_t Size = 0, T Content = T())
: m_Size(Size), m_Array(Size ? new T[m_Size] : nullptr) {
for (size_t i = 0; i < m_Size; ++i) {
m_Array[i] = Content;
}
}
DynamicArray(const DynamicArray<T>& rhs)
: m_Size(rhs.m_Size), m_Array(m_Size ? new T[m_Size] : nullptr) {
std::copy(rhs.m_Array, rhs.m_Array + m_Size, m_Array);
}
DynamicArray(DynamicArray<T>&& rhs)
: DynamicArray<T>() {
this->Swap(rhs);
//Swap(*this, rhs); //C2660
}
DynamicArray<T>& operator= (DynamicArray<T> rhs) {
this->Swap(rhs);
//Swap(*this, rhs); //C2660
return *this;
}
~DynamicArray() {
delete [] m_Array;
}
void Swap(DynamicArray<T>& rhs) {
std::swap(m_Size, rhs.m_Size);
std::swap(m_Array, rhs.m_Array);
}
private:
size_t m_Size;
T* m_Array;
};
int main() {
DynamicArray<int> DA1(4, 64);
DynamicArray<int> DA2(2, 33);
DA1 = std::move(DA2); //using move constructor
DynamicArray<int> DA3(8, 4);
DynamicArray<int> DA4(2, 55);
DA3 = DA4; //using assignment operator
Swap(DA1, DA3); //here I can call this function with 2 arguments
cout << endl;
system("pause");
}

To specify that you want to call the global Swap, you should prefix it perhaps with the scope resolution operator ::, like this ::Swap(...).
It's been a long while since I last coded in c++ but I believe the member Swap method takes precedence in the resolution of the Swap symbol, when it's used within a member method.

To explicitly use std::swap function try:
void Swap(DynamicArray<T>& rhs)
{
using std::swap;
std::swap(m_Size, rhs.m_Size);
std::swap(m_Array, rhs.m_Array);
}
DynamicArray(DynamicArray<T>&& rhs)
: DynamicArray<T>()
{
this->Swap(rhs);
}
...
Swap<int>( DA1, DA3 );
but I would remove global inline void Swap(DynamicArray<T> and start using:
DA1.Swap( DA3 );

Related

Receiving Error C2670 in Visual Studios 2019

I've searched throughout my entire code, and there aren't any other issues except for this section. The semicolon at the end of the forward-slashed line is the issue. Is there something I'm missing? Full error message below.
source\repos\Square Matrix\SquareMatrix.cpp(108,27): error C2760: syntax error: unexpected token ';', expected '{'
#pragma once
#include <stdexcept>
#include "SquareMatrix.h"
template<typename T>
class SquareMatrix
{
private:
size_t _size; //will be the size of the array. size_t makes sure i only use nonnegative integers for the size
T **_ptr;
public:
SquareMatrix(); //zero parameter constructor
SquareMatrix(const SquareMatrix& rhs); //copy constructor
~SquareMatrix(); //destructor
SquareMatrix(SquareMatrix&& rhs); //Move Constructor
SquareMatrix& operator=(const SquareMatrix& rhs); //Copy assignment Operator
SquareMatrix& operator=(SquareMatrix&& rhs); //Move Assignment Operator
void resize(size_t new_size);
T& at(int row, int column);
size_t size() const;
};
template<typename T>
void SquareMatrix<T>::resize(size_t new_size)
{
std::cout << "Input size of the new matrix: " << std::endl;
std::cin >> new_size;
for (int i = 0; i < _size; i++)
{
delete[] _ptr[i];
}
if (_ptr != nullptr)
delete[] _ptr;
if (new_size != _size)
{
_ptr = new T * [new_size];
for (int i = 0; i < new_size; i++)
{
// _ptr[i] = T *[new_size]; //
}
}
}
It seems that the issue might be in the declaration of your class SquareMatrix. You have not posted it so I cant tell for sure but I tested your method implementation with a dummy class and I don't get any errors in compilation.
Make sure that your class declaration and method declaration have this syntax:
template<class T>
class SquareMatrix {
T a, b;
public:
void resize(size_t new_size);
};
You can review the section on Class Templates to get some examples and a more through explanation.
http://www.cplusplus.com/doc/oldtutorial/templates/

How do I make std::sort not have name collision between std::swap and my namespace's templated swap?

I want to use std::sort, but the compile is failing with error C2668: std::swap: ambiguous call to overloaded function because there is a templated swap() function defined in my namespace that would be hard to get rid of. I don't care which swap it uses, but how do I make either one of them go away when compiling sort()?
I understand that it's ambiguous because my::swap is in the same namespace as my::Obj, and I don't care which version of swap gets used. I just have to overcome the namespace collision. This is part of a very large code base that I don't own so I'm hoping for a solution that is local to my code and presumably allows my::Obj and my::swapto both stay in namespace my.
namespace my
{
template<class T> void swap(T a, T b)
{
}
struct Obj
{
};
void doSortStuff()
{
std::vector<Obj> arr;
std::sort(arr.begin(), arr.end());
}
};
A workaround is to create a better overload:
// No modifiable code
namespace my
{
template<class T> void swap(T a, T b) { /*.. */ }
struct Obj { /*..*/ };
}
// Your code:
namespace my
{
void swap(Obj& lhs, Obj& rhs)
{
// my::swap<Obj&>(lhs, rhs);
std::swap(lhs, rhs);
}
}
// In namespace you want.
void doSortStuff()
{
std::vector<my::Obj> arr;
std::sort(arr.begin(), arr.end());
}
Then, between the 3 valid overloads, all are exact match, but the non-template is preferred.
Contrary to some comments and surprising to some this error happens without using namespace std. Here is a minimal example to understand what is going on:
namespace like_std
{
template<class T> void swap(T a, T b) {}
template <class T> auto test(T x, T y)
{
swap(x, y); // (1) ambiguous call
}
}
namespace my
{
template<class T> void swap(T a, T b) {}
struct Obj {};
void doStuff()
{
like_std::test(Obj{}, Obj{});
}
};
You do a call to a function from like_std and inside this function there is an unqualified call to swap. For this call:
like_std::swap is a candidate because is in the same namespace as the call to swap
my::swap is a candidate because of ADL: it's brought in because it's in the same namespace as one of the arguments to the call of swap
Since neither of those is better there is an ambiguity.
The reason why the call to swap is unqualified is so that it will pick up a custom swap if it's defined, but that works only if the custom swap is a better candidate, which is assumed for a custom swap function.
The solution, as Jarod42 showed is to define a better candidate swap function.
You are probably using namespace std;.
In this case, the compiler does not know what to choose as it makes all std:: members available without typing it automatically, where both functions are suitable:
using namespace std;
swap(a, b); //your swap
swap(a, b); //std::swap
As in this case, you have strict function calls:
std::swap(a, b); //from std
swap(a, b); // your one
This is actually a very good example of why you should avoid using namespace std. Good luck!
Update: This can be your solution - move your swap() outside of std::sort() usage:
#include <algorithm>
#include <vector>
namespace detail
{
struct someContainer
{
someContainer(int &v)
{
value = v;
}
int value;
someContainer &operator = (const someContainer & rhs)
{
this->value = rhs.value;
}
bool operator == (someContainer &rhs) const
{
return this->value == rhs.value;
}
bool operator <= (someContainer &rhs) const
{
return this->value <= rhs.value;
}
bool operator >= (someContainer &rhs) const
{
return this->value >= rhs.value;
}
bool operator > (someContainer &rhs) cosnt
{
return this->value > rhs.value;
}
bool operator < (someContainer &rhs) const
{
return this->value < rhs.value;
}
};
void doSomeStuff()
{
std::vector<someContainer> vec;
for (int i = 0; i < vec.size(); ++i)
{
vec.push_back(someContainer(i));
}
std::sort(vec.begin(), vec.end());
}
}
namespace mySwap
{
template< class T >
void swap(T &a, T &b)
{
T c = a;
a = b;
b = c;
}
}
int main()
{
detail::doSomeStuff();
return 0;
}

Template copy constructor

I need to create a copy constructor for my class MyVector.
#include <iostream>
using namespace std;
template<class T>
class MyVector{
private:
T *v;
int size;
int max;
public:
MyVector();
MyVector(const MyVector &l);
MyVector& operator=(const MyVector &lhs);
T &operator[](unsigned int i);
};
int main() {
return 0;
}
template<class T>
MyVector& MyVector<T>::operator = (const MyVector &lhs){
if (this == &lhs) return *this;
for (int i = 0; i < size; ++i){
delete v[i];
}
delete [] v;
max = lhs.max;
size = lhs.size;
v = new T[max];
for(int i = 0; i < size; ++i) {
v[i] = new T(*(lhs.v[i]));
}
return *this;
}
im getting the error: expected constructor, destructor, or type conversion before âmyVectorâ
Not sure where the problem is, I am fairly new to c++.
Thanks.
The following is the problem:
template<class T>
MyVector& MyVector<T>::operator = (const MyVector &lhs){
/* ... */
}
The return type, MyVector& should be MyVector<T>& because you're outside of the class scope, so you need to provide the template parameter there, like this:
template<class T>
MyVector<T>& MyVector<T>::operator = (const MyVector &lhs){
/* ... */
}
In the return for the function implementation, write MyVector<T>.
template<class T>
MyVector<T>& MyVector<T>::operator = (const MyVector &lhs)
{
Note that you're implementing an assignment operator, not a copy constructor.
A nice alternative is to use C++11 syntax where the return type follows the function head:
template<class T>
auto MyVector<T>::operator = (const MyVector &lhs)
-> MyVector&
{
MyVector(const MyVector &l);
should be:
MyVector(const MyVector<T> &l);
and similarly everywhere else you use MyVector as a type, since the type is not complete without the template arguments.

Overloading operator[] for a template class- c++

just wrote a code for a template array class (I know its not finished yet), and trying to remember how to overload operators (meanwhile without special difficulties...).
Anyway, while thinking of how to implement operator[] I wondered what would happen if the index is outside the boundaries of the array... I'm pretty sure it is not possible for me to return a NULL (because of the return type), right? and if so, what should I return in case the index is out of boundries?
here's the code, most of it is redundant to my question, but it might help anyone who google's operators overloading so I post the complete code...
#ifndef __MYARRAY_H
#define __MYARRAY_H
#include <iostream>
using namespace std;
template <class T>
class MyArray
{
int phisicalSize, logicalSize;
char printDelimiter;
T* arr;
public:
MyArray(int size=10, char printDelimiter=' ');
MyArray(const MyArray& other);
~MyArray() {delete []arr;}
const MyArray& operator=(const MyArray& other);
const MyArray& operator+=(const T& newVal);
T& operator[](int index);
friend ostream& operator<<(ostream& os, const MyArray& ma)
{
for(int i=0; i<ma.logicalSize; i++)
os << ma.arr[i] << ma.printDelimiter;
return os;
}
};
template <class T>
T& MyArray<T>::operator[]( int index )
{
if (index < 0 || index > logicalSize)
{
//do what???
}
return arr[index];
}
template <class T>
const MyArray<T>& MyArray<T>::operator+=( const T& newVal )
{
if (logicalSize < phisicalSize)
{
arr[logicalSize] = newVal;
logicalSize++;
}
return *this;
}
template <class T>
const MyArray<T>& MyArray<T>::operator=( const MyArray<T>& other )
{
if (this != &other)
{
delete []arr;
phisicalSize = other.phisicalSize;
logicalSize = other.logicalSize;
printDelimiter = other.printDelimiter;
arr = new T[phisicalSize];
for(int i=0; i<logicalSize; i++)
arr[i] = other.arr[i];
}
return *this;
}
template <class T>
MyArray<T>::MyArray( const MyArray& other ) : arr(NULL)
{
*this = other;
}
template <class T>
MyArray<T>::MyArray( int size, char printDelimiter ) : phisicalSize(size), logicalSize(0), printDelimiter(printDelimiter)
{
arr = new T[phisicalSize];
}
#endif
operator[] generally does no bounds checking. Most of the standard containers that can have a range utilize a separate function, at(), which is range checked and throws a std::out_of_range exception.
You likely want to implement a const T& operator[] overload, too.

Does C++ have an equivilent to Python's __setitem__

Just as the title asks, does C++ have the equivalent of Python's setitem and getitem for classes?
Basically it allows you to do something like the following.
MyClass anObject;
anObject[0] = 1;
anObject[1] = "foo";
basically, you overload the subscript operator (operator[]), and it returns a reference (so it can be read as well as written to)
You can overload the [] operator, but it's not quite the same as a separate getitem/setitem method pair, in that you don't get to specify different handling for getting and setting.
But you can get close by returning a temporary object that overrides the assignment operator.
To expand on Earwicker post:
#include <string>
#include <iostream>
template <typename Type>
class Vector
{
public:
template <typename Element>
class ReferenceWrapper
{
public:
explicit ReferenceWrapper(Element& elem)
: elem_(elem)
{
}
// Similar to Python's __getitem__.
operator const Type&() const
{
return elem_;
}
// Similar to Python's __setitem__.
ReferenceWrapper& operator=(const Type& rhs)
{
elem_ = rhs;
return *this;
}
// Helper when Type is defined in another namespace.
friend std::ostream& operator<<(std::ostream& os, const ReferenceWrapper& rhs)
{
return os << rhs.operator const Type&();
}
private:
Element& elem_;
};
explicit Vector(size_t sz)
: vec_(sz)
{
}
ReferenceWrapper<const Type> operator[](size_t ix) const
{
return ReferenceWrapper<const Type>(vec_[ix]);
}
ReferenceWrapper<Type> operator[](size_t ix)
{
return ReferenceWrapper<Type>(vec_[ix]);
}
private:
std::vector<Type> vec_;
};
int main()
{
Vector<std::string> v(10);
std::cout << v[5] << "\n";
v[5] = "42";
std::cout << v[5] << "\n";
}
It's not portable, but MSVC has __declspec(property), which also allows indexers:
struct Foo
{
void SetFoo(int index, int value) { ... }
int GetFoo(int index) { ... }
__declspec(property(propget=GetFoo, propput=SetFoo)) int Foo[];
}
other than that, Earwicker did outline the portable solution, but he's right that you'll run into many problems.