- Operator overloading - 19 Updates
- Standard C++ GUI Library Proposal - 4 Updates
- "Wondering how C++ got this far? So does its creator" By Julia Schmidt - 2 Updates
jacobnavia <jacob@jacob.remcomp.fr>: Jun 27 08:46AM +0200 Hi I have implemented operator overloading in the context of the C language, 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? Thanks in advance. jacob |
Bonita Montero <Bonita.Montero@gmail.com>: Jun 27 08:52AM +0200 Am 27.06.2020 um 08:46 schrieb jacobnavia: > 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? Impossible ! You have to have an object at each level where you apply the []-operator. If you't declare a multidimensional vector, you'd write this: #include <vector> using namespace std; int main() { vector<vector<vector<int>>> threeDimensional; // creates the the first element of the first, second and // third dimension (compile with C++17 !) threeDimensional.emplace_back().emplace_back().emplace_back(); threeDimensional[0][0][0] = 0; } |
Bonita Montero <Bonita.Montero@gmail.com>: Jun 27 09:11AM +0200 Maybe this is a more proper example: #include <vector> #include <iostream> using namespace std; int main() { vector<vector<vector<size_t>>> vvvi; vvvi.reserve( 10 ); for( size_t i = 0; i != 10; ++i ) { vector<vector<size_t>> &vvi = vvvi.emplace_back(); vvi.reserve( 10 ); for( size_t j = 0; j != 10; ++j ) { vector<size_t> &vi = vvi.emplace_back(); vi.resize( 10 ); for( size_t k = 0; k != 10; ++k ) vi[k] = i << 16 | j << 8 | k; } } size_t sum = 0; for( size_t i = 0; i != vvvi.size(); ++i ) for( size_t j = 0; j != vvvi[i].size(); ++j ) for( size_t k = 0; k != vvvi[i][j].size(); ++k ) sum += vvvi[i][j][k]; cout << "sum: " << sum << endl; } |
jacobnavia <jacob@jacob.remcomp.fr>: Jun 27 10:22AM +0200 Le 27/06/2020 à 09:11, Bonita Montero a écrit : > sum += vvvi[i][j][k]; > cout << "sum: " << sum << endl; > } Sorry but I got acob@rock64:~/lcc/book/test$ g++ tidx.cpp tidx.cpp: In function 'int main()': tidx.cpp:12:56: error: invalid initialization of non-const reference of type 'std::vector<std::vector<long unsigned int> >&' from an rvalue of type 'void' vector<vector<size_t>> &vvi = vvvi.emplace_back(); ~~~~~~~~~~~~~~~~~^~ tidx.cpp:16:50: error: invalid initialization of non-const reference of type 'std::vector<long unsigned int>&' from an rvalue of type 'void' vector<size_t> &vi = vvi.emplace_back(); ~~~~~~~~~~~~~~~~^~ jacob@rock64:~/lcc/book/test$ Must be a problem somwhere but my C++ is too weak to figure it out. Anyway thanks for your input. |
Ian Collins <ian-news@hotmail.com>: Jun 27 08:49PM +1200 On 27/06/2020 18:46, jacobnavia wrote: > 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? Some thing like: #include <array> using Column = std::array<int,2>; using Row = std::array<Column,5>; using Plane = std::array<Row,2>; int main() { Plane plane; plane[1][2][1] = 0; Column col {1,2}; plane[1][1] = col; } ? -- Ian. |
Bonita Montero <Bonita.Montero@gmail.com>: Jun 27 10:51AM +0200 > jacob@rock64:~/lcc/book/test$ > Must be a problem somwhere but my C++ is too weak to figure it out. > Anyway thanks for your input. C++ supports emplace_back with a reference-return since C++17. |
jacobnavia <jacob@jacob.remcomp.fr>: Jun 27 11:11AM +0200 Le 27/06/2020 à 10:51, Bonita Montero a écrit : >> Must be a problem somwhere but my C++ is too weak to figure it out. >> Anyway thanks for your input. > C++ supports emplace_back with a reference-return since C++17. I used: g++ -std=c++17 tidx.cpp The same error... |
Melzzzzz <Melzzzzz@zzzzz.com>: Jun 27 09:32AM > 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? You don't. Operator [] is single function. You call another [] on result of previous [], and again. -- current job title: senior software engineer skills: c++,c,rust,go,nim,haskell... press any key to continue or any other to quit... U ničemu ja ne uživam kao u svom statusu INVALIDA -- Zli Zec Svi smo svedoci - oko 3 godine intenzivne propagande je dovoljno da jedan narod poludi -- Zli Zec Na divljem zapadu i nije bilo tako puno nasilja, upravo zato jer su svi bili naoruzani. -- Mladen Gogala |
Bonita Montero <Bonita.Montero@gmail.com>: Jun 27 11:42AM +0200 >> C++ supports emplace_back with a reference-return since C++17. > I used: > g++ -std=c++17 tidx.cpp Maybe an outdated standard-libary. Look here: https://en.cppreference.com/w/cpp/container/vector/emplace_back Since C++17 the STL shoud return a reference. |
alelvb <alelvb@inwind.it>: Jun 27 01:29PM +0200 Il 27/06/20 08:46, jacobnavia ha scritto: > How do you overload the access to T? > Thanks in advance. > jacob I'm playing with 2 dimensional std::vectors, but you can extend this for arrays with a bigger number of dimensions. my code is maybe not the most orthodox but it works: //******** cut here ********* #include <initializer_list> #include <iostream> #include <vector> using uInt = long long unsigned int; template <typename T> class Matrix { public: /* =================== * the constructors * =================== */ Matrix(std::initializer_list<std::initializer_list<T>> lil); Matrix(const Matrix<T>& m) = default; Matrix(Matrix<T>&& r) = default; Matrix(uInt r, uInt c); /* =================== * member functions * =================== */ uInt rows() const { return row; } uInt columns() const { return col; } std::vector<T> operator[] (const uInt r) const { return data.at(r); } std::vector<T>& operator[] (const uInt r) { return data.at(r); } ~Matrix<T>() = default; /* =================== * the '<<' operator * =================== */ friend std::ostream& operator<< (std::ostream& out, const Matrix<T>& m) { for(uInt i=0; i != m.rows(); ++i) { for(uInt j=0; j != m.columns(); ++j) { out << m.data[i][j] << ' '; } out << '\n'; } return out; } /* =================== * data members * =================== */ private: std::vector<std::vector<T>> data; uInt row; uInt col; }; /* =================== * constructor implem * =================== */ template <typename T> Matrix<T>::Matrix(std::initializer_list<std::initializer_list<T>> lil) { uInt r=0, count=0, maxcols=0; for(auto y : lil) { ++r; std::vector<T> v; data.push_back(v); for(auto x : y) { ++count; } if(count > maxcols) maxcols = count; count=0; } row = r; col = maxcols; // initialization int i=0; for(auto y : lil) { for(auto x : y) { data.at(i).push_back(x); } ++i; } } /* =================== * the main function * =================== */ int main() { Matrix<double> m {{0,1,2},{0,1,1},{1,0,1}}; std::cout << m << '\n'; } |
"Alf P. Steinbach" <alf.p.steinbach+usenet@gmail.com>: Jun 27 04:51PM +0200 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? > 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 |
jacobnavia <jacob@jacob.remcomp.fr>: Jun 27 05:13PM +0200 Le 27/06/2020 à 11:42, Bonita Montero a écrit : > Maybe an outdated standard-libary. Look here: > https://en.cppreference.com/w/cpp/container/vector/emplace_back > Since C++17 the STL shoud return a reference. YES! I compiled in my macintosh and it worked. Before I was compiling in an arm. Apparently the library of the arm system is a bit old Thanks |
Juha Nieminen <nospam@thanks.invalid>: Jun 27 03:33PM > I have implemented operator overloading in the context of the C > language What does that even mean? |
Juha Nieminen <nospam@thanks.invalid>: Jun 27 03:36PM > You don't. Operator [] is single function. You call another [] on result > of previous [], and again. I wonder if it would break anything if support for multidimensional operator[] would be added. It could work simply like this: class MyClass { public: void operator[](std::size_t i1, std::size_t i2) { std::cout << "[" << i1 << "][" << i2 << "]\n"; } }; void foo() { MyClass obj; obj[10][20]; } Why add this kind of support? Because it would significantly simplify overloading multidimensional indexing. |
David Brown <david.brown@hesbynett.no>: Jun 27 06:28PM +0200 On 27/06/2020 17:36, Juha Nieminen wrote: > } > Why add this kind of support? Because it would significantly > simplify overloading multidimensional indexing. There is, I believe, I move towards sane multi-dimensional indexing support in C++, in the form "obj[10, 20]" - the use of the comma operator is deprecated within array expressions in C++20. But it will take many generations of C++ standards before such array expressions can be used - backwards compatibility is a bugger when you have to keep supporting language design mistakes. Personally, I think /all/ use of the comma operator should have been deprecated. Another way of making multi-dimensional arrays with nice indexing is to overload the function call operator, so that you can write: obj(10, 20) |
jacobnavia <jacob@jacob.remcomp.fr>: Jun 27 06:34PM +0200 Le 27/06/2020 à 16:51, Alf P. Steinbach a écrit : > Some macro-based support for function overloading was added in C11, but > is that what you have leveraged? > Or what? I repeat. I am the developer of the lcc-win compiler system, and in that compiler I have implemented operator overloading, roughly similar to c++ with some differences. >> 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. In my system you have the operator [ ] (accessing an array for reading) and the operator [ ] = (accessing an array for writing) The last one takes 3 arguments: the object, the index, and the value. Now, I wanted to know how C++ manages multi-dimensional array access, and apparently it doesn't. So I have no c++ compatibility problem since there isn't anything there. Thanks for your input. I compiled your code and it runs ok, but I would like to keep the [] notation. jacob |
jacobnavia <jacob@jacob.remcomp.fr>: Jun 27 06:40PM +0200 Le 27/06/2020 à 17:33, Juha Nieminen a écrit : >> I have implemented operator overloading in the context of the C >> language > What does that even mean? typedef struct { double real,double imag; } cmplx; cmplx operator +(complx a,cmplx b) { cmplx result; result.real = a.real+b.real; result.imag = a.imag+b.imag; return result; } int main(void) { cmplx a,b={2,3},c={4,5}; c = a+b; } This compiles in the lcc-win compiler system. It is called "operator overloading" and many languages support it like Fortran, c# and others. It has been a standard feature of my compiler system since 2005. |
Paavo Helde <eesnimi@osa.pri.ee>: Jun 27 09:05PM +0300 27.06.2020 19:28 David Brown kirjutas: > be used - backwards compatibility is a bugger when you have to keep > supporting language design mistakes. Personally, I think /all/ use of > the comma operator should have been deprecated. The comma operator is essential for for. There are uncountably many for loop expressions using the comma operator and it can be never deprecated there. For [] I agree: ',' does not mean comma operator inside (), [] should behave the same, just for symmetry. For lambda [] this already works so. |
Bonita Montero <Bonita.Montero@gmail.com>: Jun 27 08:32PM +0200 > This compiles in the lcc-win compiler system. It is called "operator > overloading" and many languages support it like Fortran, c# and others. > It has been a standard feature of my compiler system since 2005. If you are not writing your own complex-class for educational purposes: you can #include <complex> and thereby have a full blown complex-class with all appropriate operators. |
Cholo Lennon <chololennon@hotmail.com>: Jun 26 10:31PM -0300 On 6/26/20 6:40 AM, Alessandro Volturno wrote: > features. It would be very useful, in my opinion, to offer the > programmer a unique, standard way to handle the screen and to permit a > uniform representation of these features graphically. I don't know if your first assertion ("console programs are now widely superseded by graphical UI") is true. Could you provide some source/stats for that? IMHO the GUI apps are just the tip of the iceberg... but a more or less 50-50 proportion is not crazy at all. -- Cholo Lennon Bs.As. ARG |
alelvb <alelvb@inwind.it>: Jun 27 10:13AM +0200 Il 27/06/20 03:31, Cholo Lennon ha scritto: > superseded by graphical UI") is true. Could you provide some > source/stats for that? IMHO the GUI apps are just the tip of the > iceberg... but a more or less 50-50 proportion is not crazy at all. No... I cannot give any statistics. I'm not competent on the matter. I said that from my limited experience as amateur self-taught programmer. Sorry : ) |
Manfred <noname@add.invalid>: Jun 27 05:56PM +0200 On 6/27/2020 10:13 AM, alelvb wrote: > matter. I said that from my limited experience as amateur > self-taught programmer. > Sorry : ) Even without accurate statistics one can easily get some idea: a typical Linux (or *nix for that matter) server distribution does not include an X server, which means there is no GUI at all. It is an easy guess that there is quite a lot of server code running out there. |
Manfred <noname@add.invalid>: Jun 27 06:07PM +0200 >> benefit for the widespread of C++. > Jave has a standard GUI built in to the JVM but it ended up being lowest common > denominator and everyone hated it. [...] > control logic and low level access to the system. It is the job of libraries to > use that low level access to provide I/O and other support services that will > vary considerably from one machine to another. Agreed, C++ is not meant o be an "all purpose" language - Stroustrup himself says that no programmer should limit themselves to one language only. This is different from Java, for which one of the goals was to run the entire system (and for example Android followed this path by deprecating any non-Java application) - and still the result is hardly usable unless the GUI subsystem is deeply rebuilt. |
Juha Nieminen <nospam@thanks.invalid>: Jun 27 06:26AM > That's what many think of as vector graphics. After all you pass it the > endpoints of a vector, not the intervening pixels. And it can do > antialiased lines of sorts. Generally "vector graphics" refers to drawing pictures using drawing elements like lines, curves, ellipses, splines and so on and so forth, and most often this supports defining line thickness, color, fill color, fill pattern, and oftentimes all kinds of effects. Most usually high-quality antialiasing is supported to avoid a pixelated look. It is what, for example, the SVG file format is all about. See https://en.wikipedia.org/wiki/Vector_graphics Even at its simplest a "vector graphics" library ought to support at least a few primitivies, like lines, circles, rectangles, etc. |
Manfred <noname@add.invalid>: Jun 27 05:39PM +0200 On 6/27/2020 8:26 AM, Juha Nieminen wrote: > See https://en.wikipedia.org/wiki/Vector_graphics > Even at its simplest a "vector graphics" library ought to support > at least a few primitivies, like lines, circles, rectangles, etc. There is a fundamental difference between a data format like SVG or PS and a rendering API like OpenGL that is deliberately kept close to the hardware. The former provides higher level primitives to ease the job of the content provider. Runtime performance is of secondary concern. The latter aims at maximum performance by providing as direct as possible access to hardware functions. It could certainly be possible to make GPU boards that render SVG directly, but this kind of trajectory would clash with the differences between the hardware development cycle and standards evolution. I'll admit that I am not up to date with the latest standards, however curves and splines are supported by the earlier versions of OpenGL (still available on all implementations) as part of the utility library, that substantially converts them into step-linear paths. Antialiasing is also part of the OpenGL API as a /hint/, which means that implementations are free to ignore it, but this is a problem of QoI rather than of OpenGL itself. What I find more meaningful is that one fundamental power of vector graphics is that it can perform exact and efficient vector *transformations* like scaling, rotations, gradients and textures - all of this (and much more) has been part of OpenGL since day one. |
You received this digest because you're subscribed to updates for this group. You can change your settings on the group membership page. To unsubscribe from this group and stop receiving emails from it send an email to comp.lang.c+++unsubscribe@googlegroups.com. |
No comments:
Post a Comment