the Q is how to this kind of operator=
that it will work on:
int t = v[3]; // her i return by Value
v[3] = 8 ; // her i need to return by refrence (pointer to V[3] add')
will V is a Vector class (template class in my case)
template <class T>
T& Vector<T>::operator[](const int Index) const
{
if(Index > -1 && Index < this->Size)
{
return &this->Array[Index];
}
else
{
cerr <<"VECTOR_INVALID_INDEX"<<endl;
return NULL;
}
};
There are several errors in this example. this is already a pointer. Doing &this is almost certainly not what you meant to do here. The other problem you are having is that you are returning a reference to T but this is const in this context. this->Array[Index] is const T which cannot bind to T&. Add a const and return const T& instead. Thirdly, this->Size is not calling the method Size, you forgot parentheses. The fourth problem is a reference binding to NULL. You will have to decide on another approach. The usual way to indicate that an operation cannot be completed is to throw an exception. std::vector::at throws std::out_of_range from header stdexcept.
template <class T>
const T& Vector<T>::operator[](const int Index) const
//^^^ add const here
{
if (Index > -1 && Index < this->Size())
// Add parentheses ^^
{
return this->Array[Index];
// ^ No need for &
}
else
{
throw std::out_of_range("VECTOR_INVALID_INDEX");
}
};
You will probably want to add a non-const version as well, since this will fail for the example v[3] = 8;. Define this method as well with the same body :
T& Vector<T>::operator[](const int Index);
Related
Consider the task of writing an indexable class which automatically synchronizes its state with some external data-store (e.g. a file). In order to do this the class would need to be made aware of changes to the indexed value which might occur. Unfortunately the usual approach to overloading operator[] does not allow for this, for example...
Type& operator[](int index)
{
assert(index >=0 && index < size);
return state[index];
}
I there any way to distinguish between a value being accessed and a value being modified?
Type a = myIndexable[2]; //Access
myIndexable[3] = a; //Modification
Both of these cases occur after the function has returned. Is there some other approach to overloading operator[] which would perhaps make more sense?
From the operator[] you can only really tell access.
Even if the external entity uses the non cost version this does not mean that a write will take place rather that it could take place.
As such What you need to do is return an object that can detect modification.
The best way to do this is to wrap the object with a class that overrides the operator=. This wrapper can then inform the store when the object has been updated. You would also want to override the operator Type (cast) so that a const version of the object can be retrieved for read accesses.
Then we could do something like this:
class WriteCheck;
class Store
{
public:
Type const& operator[](int index) const
{
return state[index];
}
WriteCheck operator[](int index);
void stateUpdate(int index)
{
// Called when a particular index has been updated.
}
// Stuff
};
class WriteCheck
{
Store& store;
Type& object;
int index;
public: WriteCheck(Store& s, Type& o, int i): store(s), object(o), index(i) {}
// When assignment is done assign
// Then inform the store.
WriteCheck& operator=(Type const& rhs)
{
object = rhs;
store.stateUpdate(index);
}
// Still allow the base object to be read
// From within this wrapper.
operator Type const&()
{
return object;
}
};
WriteCheck Store::operator[](int index)
{
return WriteCheck(*this, state[index], index);
}
An simpler alternative is:
Rather than provide the operator[] you provide a specific set method on the store object and only provide read access through the operator[]
You can have (the non-const) operator[] return a proxy object that keeps a reference or pointer to the container, and in which operator= signals the container of the update.
(The idea of using const vs non-const operator[] is a red herring... you may know that you've just given away non-const access to the object, but you don't know if that access is still being used for a read or a write, when that write completes, or have any mechanism for updating the container thereafter.)
Another elegant (IMHO) solution...
Actually it is based on the fact that the const overload is called only when used on const object.
Lets first create two [] overloads - as it is required, but using different locations:
Type& operator[](int index)
{
assert(index >=0 && index < size);
return stateWrite[index];
}
const Type& operator[](int index) const
{
assert(index >=0 && index < size);
return stateRead[index];
}
Now you should create a shadow reference of your object when you need to "read" it as follows:
const Indexable& myIndexableRead = myIndexable; // create the shadow
Type a = myIndexableRead[2]; //Access
myIndexable[3] = a; //Modification
Creating this shadow declaration does not actually create anything in the memory. It just creates another name for your object with "const" access. It is all resolved at the compilation stage (including usage of const overload) and does not affect anything in runtime - neither memory nor performance.
And the bottom line - it is much more elegant (IMHO) than creating any assignment proxies, etc. I must state that the statement "From the operator[] you can only really tell access" is incorrect. According to the C++ Standard, returning dynamically allocatted object or global variable by reference is ultimate way to allow its direct modification, including [] overload case.
Following code has been tested:
#include <iostream>
using namespace std;
class SafeIntArray {
int* numbers;
int size;
static const int externalValue = 50;
public:
SafeIntArray( unsigned int size = 20 ) {
this->size = size;
numbers = new int[size];
}
~SafeIntArray() {
delete[] numbers;
}
const int& operator[]( const unsigned int i ) const {
if ( i < size )
return numbers[i];
else
return externalValue;
}
int& operator[]( const unsigned int i ) {
if ( i < size )
return numbers[i];
else
return *numbers;
}
unsigned int getSize() { return size; }
};
int main() {
SafeIntArray arr;
const SafeIntArray& arr_0 = arr;
int size = arr.getSize();
for ( int i = 0; i <= size ; i++ )
arr[i] = i;
for ( int i = 0; i <= size ; i++ ) {
cout << arr_0[i] << ' ';
}
cout << endl;
return 0;
}
And the results are:
20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 50
Return a proxy object which will have:
operator=(Type const &) overloaded for writes
operator Type() for reads
in the access example you give you can get a distinction by using a const version:
const Type& operator [] ( int index ) const;
on a sidenote, using size_t as index gets rid of the need for checking if index >= 0
#include "stdafx.h"
#include <iostream>
template<typename T>
class MyVector
{
T* _Elem; // a pointer to the elements
int _Size; // the size
public:
// constructor
MyVector(int _size):_Size(_size), _Elem(new T[_size])
{
// Initialize the elemets
for( int i=0; i< _size; ++i )
_Elem[i] = 0.0;
}
// destructor to cleanup the mess
~MyVector(){ delete []_Elem; }
public:
// the size of MyVector
int Size() const
{
return _Size;
}
// overload subscript operator
T& operator[]( int i )
{
return _Elem[i];
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyVector<int> vec(10);
vec[0] =10;
vec[1] =20;
vec[2] =30;
vec[3] =40;
vec[4] =50;
std::cout<<"Print vector Element "<<std::endl;
for (int i = 0; i < vec.Size(); i++)
{
std::cout<<"Vec["<<i<<"] = "<<vec[i]<<std::endl;
}
return 0;
}
Background
I'm working with an embedded platform with the following restrictions:
No heap
No Boost libraries
C++11 is supported
I've dealt with the following problem a few times in the past:
Create an array of class type T, where T has no default constructor
The project only recently added C++11 support, and up until now I've been using ad-hoc solutions every time I had to deal with this. Now that C++11 is available, I thought I'd try to make a more general solution.
Solution Attempt
I copied an example of std::aligned_storage to come up with the framework for my array type. The result looks like this:
#include <type_traits>
template<class T, size_t N>
class Array {
// Provide aligned storage for N objects of type T
typename std::aligned_storage<sizeof(T), alignof(T)>::type data[N];
public:
// Build N objects of type T in the aligned storage using default CTORs
Array()
{
for(auto index = 0; index < N; ++index)
new(data + index) T();
}
const T& operator[](size_t pos) const
{
return *reinterpret_cast<const T*>(data + pos);
}
// Other methods consistent with std::array API go here
};
This is a basic type - Array<T,N> only compiles if T is default-constructible. I'm not very familiar with template parameter packing, but looking at some examples led me to the following:
template<typename ...Args>
Array(Args&&... args)
{
for(auto index = 0; index < N; ++index)
new(data + index) T(args...);
}
This was definitely a step in the right direction. Array<T,N> now compiles if passed arguments matching a constructor of T.
My only remaining problem is constructing an Array<T,N> where different elements in the array have different constructor arguments. I figured I could split this into two cases:
1 - User Specifies Arguments
Here's my stab at the CTOR:
template<typename U>
Array(std::initializer_list<U> initializers)
{
// Need to handle mismatch in size between arg and array
size_t index = 0;
for(auto arg : initializers) {
new(data + index) T(arg);
index++;
}
}
This seems to work fine, aside from needing to handle a dimension mismatch between the array and initializer list, but there are a number of ways to deal with that that aren't important. Here's an example:
struct Foo {
explicit Foo(int i) {}
};
void bar() {
// foos[0] == Foo(0)
// foos[1] == Foo(1)
// ..etc
Array<Foo,10> foos {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
}
2 - Arguments Follow Pattern
In my previous example, foos is initialized with an incrementing list, similar to std::iota. Ideally I'd like to support something like the following, where range(int) returns SOMETHING that can initialize the array.
// One of these should initialize foos with parameters returned by range(10)
Array<Foo,10> foosA = range(10);
Array<Foo,10> foosB {range(10)};
Array<Foo,10> foosC = {range(10)};
Array<Foo,10> foosD(range(10));
Googling has shown me that std::initializer_list isn't a "normal" container, so I don't think there's any way for me to make range(int) return a std::initializer_list depending on the function parameter.
Again, there are a few options here:
Parameters specified at run-time (function return?)
Parameters specified at compile-time (constexpr function return? templates?)
Questions
Are there any issues with this solution so far?
Does anyone have a suggestion to generate constructor parameters? I can't think of a solution at runtime or compile-time other than hard-coding an std::initializer_list, so any ideas are welcome.
If i understand your problem correctly, I've also stumbled across std::array's total inflexibility regarding element construction in favor of aggregate initialization (and an absense of statically-allocated container with flexible element contruction options). The best approach I came up with was creating a custom array-like container which accepts an iterator to construct it's elements.
This is totally flexible solution:
Works for both fixed-size and dynamic-sized containers
Can pass different or same parameters to element constructors
Can call constructors with one or multiple (tuple piecewise construction) arguments, or even different constructors for different elements (with inversion of control)
For your example it would be like:
const size_t SIZE = 10;
std::array<int, SIZE> params;
for (size_t c = 0; c < SIZE; c++) {
params[c] = c;
}
Array<Foo, SIZE> foos(iterator_construct, ¶ms[0]); //iterator_construct is a special tag to call specific constructor
// also, we are able to pass a pointer as iterator, since it has both increment and dereference operators
Note: you can totally skip parameters array allocation here by using custom iterator class, which calculates it's value from it's position on-the-fly.
For multiple-argument constructor that would be:
const size_t SIZE = 10;
std::array<std::tuple<int, float>, SIZE> params; // will call Foo(int, float)
for (size_t c = 0; c < SIZE; c++) {
params[c] = std::make_tuple(c, 1.0f);
}
Array<Foo, SIZE> foos(iterator_construct, piecewise_construct, ¶ms[0]);
Concrete implementation example is kinda big piece of code, so please let me know if you want more insights into implementation details besides the general idea - I will update my answer then.
I'd use a factory lambda.
The lambda takes a pointer to where to construct and an index, and is responsible for constructing.
This makes copy/move easy to write as well, which is a good sign.
template<class T, std::size_t N>
struct my_array {
T* data() { return (T*)&buffer; }
T const* data() const { return (T const*)&buffer; }
// basic random-access container operations:
T* begin() { return data(); }
T const* begin() const { return data(); }
T* end() { return data()+N; }
T const* end() const { return data()+N; }
T& operator[](std::size_t i){ return *(begin()+i); }
T const& operator[](std::size_t i)const{ return *(begin()+i); }
// useful utility:
bool empty() const { return N!=0; }
T& front() { return *begin(); }
T const& front() const { return *begin(); }
T& back() { return *(end()-1); }
T const& back() const { return *(end()-1); }
std::size_t size() const { return N; }
// construct from function object:
template<class Factory,
typename std::enable_if<!std::is_same<std::decay_t<Factory>, my_array>::value, int> =0
>
my_array( Factory&& factory ) {
std::size_t i = 0;
try {
for(; i < N; ++i) {
factory( (void*)(data()+i), i );
}
} catch(...) {
// throw during construction. Unroll creation, and rethrow:
for(std::size_t j = 0; j < i; ++j) {
(data()+i-j-1)->~T();
}
throw;
}
}
// other constructors, in terms of above naturally:
my_array():
my_array( [](void* ptr, std::size_t) {
new(ptr) T();
} )
{}
my_array(my_array&& o):
my_array( [&](void* ptr, std::size_t i) {
new(ptr) T( std::move(o[i]) );
} )
{}
my_array(my_array const& o):
my_array( [&](void* ptr, std::size_t i) {
new(ptr) T( o[i] );
} )
{}
my_array& operator=(my_array&& o) {
for (std::size_t i = 0; i < N; ++i)
(*this)[i] = std::move(o[i]);
return *this;
}
my_array& operator=(my_array const& o) {
for (std::size_t i = 0; i < N; ++i)
(*this)[i] = o[i];
return *this;
}
private:
using storage = typename std::aligned_storage< sizeof(T)*N, alignof(T) >::type;
storage buffer;
};
it defines my_array(), but that is only compiled if you try to compile it.
Supporting initializer list is relatively easy. Deciding what to do when the il isn't long enough, or too long, is hard. I think you might want:
template<class Fail>
my_array( std::initializer_list<T> il, Fail&& fail ):
my_array( [&](void* ptr, std::size_t i) {
if (i < il.size()) new(ptr) T(il[i]);
else fail(ptr, i);
} )
{}
which requires you pass in a "what to do on fail". We could default to throw by adding:
template<class WhatToThrow>
struct throw_when_called {
template<class...Args>
void operator()(Args&&...)const {
throw WhatToThrow{"when called"};
}
};
struct list_too_short:std::length_error {
list_too_short():std::length_error("list too short") {}
};
template<class Fail=ThrowWhenCalled<list_too_short>>
my_array( std::initializer_list<T> il, Fail&& fail={} ):
my_array( [&](void* ptr, std::size_t i) {
if (i < il.size()) new(ptr) T(il[i]);
else fail(ptr, i);
} )
{}
which if I wrote it right, makes a too-short initializer list cause a meaningful throw message. On your platform, you could just exit(-1) if you don't have exceptions.
I am working on some project and have problems with duplicating function code. Is there a way to declare only single signature of function which will work for both const and non-const params? Implementation of const and non-const functions are the same.
#include <iostream>
template <class Data>
struct Processor {
int process(const Data &data)
{
return 42;
}
int process(Data &data)
{
return 42;
}
};
int main() {
using data_type = int;
data_type non_const_data = 1;
const data_type const_data = 2;
std::cout << Processor<data_type>().process(non_const_data) << std::endl;
std::cout << Processor<data_type>().process(const_data) << std::endl;
return 0;
}
Example http://ideone.com/tv0TsF
THANKS FOR YOUR ANSWERS
UPDATE
And what about this example?
#include <iostream>
#include <vector>
template <class Container, class Function>
struct Invoker {
const Container& invoke(const Container &container, Function function)
{
for (auto &value : container) function(value);
}
Container& invoke(Container &container, Function function)
{
for (auto &value : container) function(value);
}
};
int main() {
std::vector<int> container {1, 2, 3};
auto fn = [](int val) {
std::cout << val << std::endl;
};
Invoker<decltype(container), decltype(fn)>().invoke(container, fn);
return 0;
}
http://ideone.com/KnyGdT
If implementation of both functions are same, then provide const parameter function only. It will work both for non-const and const object in your case.
However, if you want to keep the both the function, you can implement non-const parameter function in terms of const parameter function. It will help you to avoid duplicate code.
int process(const Data &data)
{
return 42;
}
int process(Data &data)
{
return process(static_cast<const Data&>data);
}
I'd suggest declaring only the most restrictive one, that being the one that expects a const param. Should there be an issue of sending a non-const pointer/reference into it, you can always make it const before calling the method.
Yes:
int process(const Data &data)
{
return 42;
}
This can be called with Data, Data &, and Data const &, and anything convertible to Data. A const reference can bind to a non-const object or reference.
It might not be exactly what you are looking for, but a similar situation arise in the case of const vs non-const member functions. Sometimes, say for instance in an access function, you would like to have two versions, one usable if the object is const and the other usable when the object is non-const.
struct MyString {
char & at(int index) {
if (index < size) {
return data[index];
else throw std::range_error("Index out of range");
}
char at(int index) const {
if (index < size) {
return data[index];
else throw std::range_error("Index out of range");
}
};
Now these functions look very similar, why can't I reuse one to implement the other?
The answer is you can, but it requires some very careful casting, first of all the general advice is to call the const-function from the non-const. As you can usually guarantee that calling a const function will be safe even from a non-const context. The call to the const-function will not actually change the object after all. (There are exceptions as with mutable variables, or the reverse of what I'm about to propose just now.)
The solution (according to More Effective C++), is use const cast to call the const version from the non-const:
const char & at(int index) const {
if (index < size) {
return data[index];
else throw std::range_error("Index out of range");
}
char & at(int index) {
return const_cast<char &>( static_cast<const MyString>(this)->at(index) );
}
This functions in two steps. First, cast this to a const pointer, that will allow us to invoke the const-version of at(). Then, once we return a const-reference to the element, cast it to a writeable reference.
I am trying to make a program that demonstrates use of templates and overloaded operators for my CS class. Here is relevant code:
main:
ArrayTemplate<int> number(0);
number[0] = 1;
number[1] = 2;
number[2] = 3;
ArrayTemplate<string> word("na");
word[0] = "One";
word[1] = "Two";
word[2] = "Three";
header:
template<class T>
T& operator [](const int index)
{
if(index >= 0 && index < ARRAY_MAX_SIZE)
return items[index];
else
{
cerr << "INDEX OUT OF BOUNDS!!!";
exit(1);
}
}
The problem is that when I try to use my overloaded subscript operator I get the error message shown in title: "No such operator "[]" matches these operands" Im not exactly sure why. It does it for both my integer array and my string array. Any help is appreciated.
You really need to show the full definition of ArrayTemplate.
This is how you probably want it to look:
template<class T>
class ArrayTemplate {
public:
// ...
T& operator [](const int index)
{
if(index >= 0 && index < ARRAY_MAX_SIZE)
return items[index];
else
{
cerr << "INDEX OUT OF BOUNDS!!!";
exit(1);
}
}
// ...
};
Note that operator[] isn't templated; only the class is.
With your current code you would have to do it like this:
number<int>[0] = 1;
number<int>[1] = 2;
number<int>[2] = 3;
Which obviously goes against your intention.
template<class T>
T& operator [](const int index)
This declaration would be called e.g. as object.operator[] < type >( 5 ). Note that type needs to be provided as a template argument. Because there's no way to supply such an argument in an expression using [], the operator overload doesn't work.
Probably you don't want the template< class T > at all. Just get rid of it:
T& operator [](const int index)
If you define the function outside the class {} scope, then it would look like this:
template<class T>
T& ArrayTemplate<T>::operator [](const int index)
In this case, the template<class T> line re-introduces the parameter in order to get back into the class template.
Consider the task of writing an indexable class which automatically synchronizes its state with some external data-store (e.g. a file). In order to do this the class would need to be made aware of changes to the indexed value which might occur. Unfortunately the usual approach to overloading operator[] does not allow for this, for example...
Type& operator[](int index)
{
assert(index >=0 && index < size);
return state[index];
}
I there any way to distinguish between a value being accessed and a value being modified?
Type a = myIndexable[2]; //Access
myIndexable[3] = a; //Modification
Both of these cases occur after the function has returned. Is there some other approach to overloading operator[] which would perhaps make more sense?
From the operator[] you can only really tell access.
Even if the external entity uses the non cost version this does not mean that a write will take place rather that it could take place.
As such What you need to do is return an object that can detect modification.
The best way to do this is to wrap the object with a class that overrides the operator=. This wrapper can then inform the store when the object has been updated. You would also want to override the operator Type (cast) so that a const version of the object can be retrieved for read accesses.
Then we could do something like this:
class WriteCheck;
class Store
{
public:
Type const& operator[](int index) const
{
return state[index];
}
WriteCheck operator[](int index);
void stateUpdate(int index)
{
// Called when a particular index has been updated.
}
// Stuff
};
class WriteCheck
{
Store& store;
Type& object;
int index;
public: WriteCheck(Store& s, Type& o, int i): store(s), object(o), index(i) {}
// When assignment is done assign
// Then inform the store.
WriteCheck& operator=(Type const& rhs)
{
object = rhs;
store.stateUpdate(index);
}
// Still allow the base object to be read
// From within this wrapper.
operator Type const&()
{
return object;
}
};
WriteCheck Store::operator[](int index)
{
return WriteCheck(*this, state[index], index);
}
An simpler alternative is:
Rather than provide the operator[] you provide a specific set method on the store object and only provide read access through the operator[]
You can have (the non-const) operator[] return a proxy object that keeps a reference or pointer to the container, and in which operator= signals the container of the update.
(The idea of using const vs non-const operator[] is a red herring... you may know that you've just given away non-const access to the object, but you don't know if that access is still being used for a read or a write, when that write completes, or have any mechanism for updating the container thereafter.)
Another elegant (IMHO) solution...
Actually it is based on the fact that the const overload is called only when used on const object.
Lets first create two [] overloads - as it is required, but using different locations:
Type& operator[](int index)
{
assert(index >=0 && index < size);
return stateWrite[index];
}
const Type& operator[](int index) const
{
assert(index >=0 && index < size);
return stateRead[index];
}
Now you should create a shadow reference of your object when you need to "read" it as follows:
const Indexable& myIndexableRead = myIndexable; // create the shadow
Type a = myIndexableRead[2]; //Access
myIndexable[3] = a; //Modification
Creating this shadow declaration does not actually create anything in the memory. It just creates another name for your object with "const" access. It is all resolved at the compilation stage (including usage of const overload) and does not affect anything in runtime - neither memory nor performance.
And the bottom line - it is much more elegant (IMHO) than creating any assignment proxies, etc. I must state that the statement "From the operator[] you can only really tell access" is incorrect. According to the C++ Standard, returning dynamically allocatted object or global variable by reference is ultimate way to allow its direct modification, including [] overload case.
Following code has been tested:
#include <iostream>
using namespace std;
class SafeIntArray {
int* numbers;
int size;
static const int externalValue = 50;
public:
SafeIntArray( unsigned int size = 20 ) {
this->size = size;
numbers = new int[size];
}
~SafeIntArray() {
delete[] numbers;
}
const int& operator[]( const unsigned int i ) const {
if ( i < size )
return numbers[i];
else
return externalValue;
}
int& operator[]( const unsigned int i ) {
if ( i < size )
return numbers[i];
else
return *numbers;
}
unsigned int getSize() { return size; }
};
int main() {
SafeIntArray arr;
const SafeIntArray& arr_0 = arr;
int size = arr.getSize();
for ( int i = 0; i <= size ; i++ )
arr[i] = i;
for ( int i = 0; i <= size ; i++ ) {
cout << arr_0[i] << ' ';
}
cout << endl;
return 0;
}
And the results are:
20 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 50
Return a proxy object which will have:
operator=(Type const &) overloaded for writes
operator Type() for reads
in the access example you give you can get a distinction by using a const version:
const Type& operator [] ( int index ) const;
on a sidenote, using size_t as index gets rid of the need for checking if index >= 0
#include "stdafx.h"
#include <iostream>
template<typename T>
class MyVector
{
T* _Elem; // a pointer to the elements
int _Size; // the size
public:
// constructor
MyVector(int _size):_Size(_size), _Elem(new T[_size])
{
// Initialize the elemets
for( int i=0; i< _size; ++i )
_Elem[i] = 0.0;
}
// destructor to cleanup the mess
~MyVector(){ delete []_Elem; }
public:
// the size of MyVector
int Size() const
{
return _Size;
}
// overload subscript operator
T& operator[]( int i )
{
return _Elem[i];
}
};
int _tmain(int argc, _TCHAR* argv[])
{
MyVector<int> vec(10);
vec[0] =10;
vec[1] =20;
vec[2] =30;
vec[3] =40;
vec[4] =50;
std::cout<<"Print vector Element "<<std::endl;
for (int i = 0; i < vec.Size(); i++)
{
std::cout<<"Vec["<<i<<"] = "<<vec[i]<<std::endl;
}
return 0;
}