On 27.06.2020 08:46, jacobnavia wrote:
> Hi
>
> I have implemented operator overloading in the context of the C
> language,
I don't quite see what that could be about.
Some macro-based support for function overloading was added in C11, but
is that what you have leveraged?
Or what?
> and I have a quetstion concerning the behavior of C++ with the
> operator [ ] (indexing) and multi-dimensional arrays.
>
> Supposing I have a 3 dimensional array of some type T.
>
> T table[2][5][2]; // 2 planes, 5 rows, 2 columns
>
> How do you overload the access to T?
Generally you don't, because operator[] only takes a single argument.
That single argument can of course be a struct with two or more indices,
and/or the indexing result can be something that can further indexed.
The struct thing is just impractical notation. The indexable result
thing can be as simple as returning a pointer, but in this case it
exposes the array internals. Alternatively the result can be a proxy
object but that's both complex and bug prone and possibly inefficient.
So, for general indexing of a multidimensional array it's common to use
either the function call operator `operator()`, and/or named indexing
functions with names such as `at` or `item`.
Example:
-----------------------------------------------------------------------
#include <stddef.h> // ptrdiff_t
#include <array> // std::array
#include <utility> // std::enable_if, std::move
#include <vector> // std::vector
namespace my {
using
std::array,
std::enable_if_t, std::move,
std::vector;
using Size = ptrdiff_t;
using Index = ptrdiff_t;
template< int arity_param, class Value_param >
class Multidimensional_array_
{
public:
static constexpr int arity = arity_param;
using Value = Value_param;
static_assert( arity > 0 );
private:
vector<Value> m_items;
array<Size, arity> m_sizes;
template< class... Indices >
auto index_for( const Indices... index_args )
-> Index
{
const array<Index, arity> indices = {index_args...};
Size weight = 1;
Index result = 0;
for( int i = 0; i < arity; ++i ) {
result += indices[i]*weight;
weight *= m_sizes[i];
}
return result;
}
public:
// The first size is "innermost", opposite of a raw
multidimensional array.
template<
class... Size_types,
class = enable_if_t< sizeof...( Size_types ) == arity >
>
Multidimensional_array_( const Size_types... sizes ):
m_items( (1 * ... * sizes) ),
m_sizes{ sizes... }
{}
template<
class... Index_types,
class = enable_if_t< sizeof...( Index_types ) == arity >
>
auto operator()( const Index_types... indices ) const
-> const Value&
{ return m_items[index_for( indices... )]; }
template<
class... Index_types,
class = enable_if_t< sizeof...( Index_types ) == arity >
>
auto operator()( const Index_types... indices )
-> Value&
{ return m_items[index_for( indices... )]; }
Multidimensional_array_( const Multidimensional_array_& other )
= default;
Multidimensional_array_( Multidimensional_array_&& other ) =
default;
auto size( const int dimension ) const
-> Size
{ return m_sizes[dimension]; }
};
template< class Value_param >
using Array_2d = Multidimensional_array_<2, Value_param>;
template< class Value_param >
using Array_3d = Multidimensional_array_<3, Value_param>;
} // namespace my
#include <iomanip>
#include <iostream>
using
std::setw,
std::cout, std::endl;
auto main()
-> int
{
auto box = my::Array_3d<double>( 2, 5, 2 );
for( int z = 0; z < box.size( 2 ); ++z ) {
for( int y = 0; y < box.size( 1 ); ++y ) {
for( int x = 0; x < box.size( 0 ); ++x ) {
box( x, y, z ) = 100*(z + 1) + 10*(y + 1) + (x + 1);
}
}
}
for( int z = 0; z < box.size( 2 ); ++z ) {
for( int y = 0; y < box.size( 1 ); ++y ) {
for( int x = 0; x < box.size( 0 ); ++x ) {
cout << setw( 4 ) << box( x, y, z );
}
cout << endl;
}
cout << endl;
}
}
-----------------------------------------------------------------------
- Alf