03.12.2012 Views

C++ for Scientists - Technische Universität Dresden

C++ for Scientists - Technische Universität Dresden

C++ for Scientists - Technische Universität Dresden

SHOW MORE
SHOW LESS

You also want an ePaper? Increase the reach of your titles

YUMPU automatically turns print PDFs into web optimized ePapers that Google loves.

84 CHAPTER 3. CLASSES<br />

Approach 3: Returning proxies<br />

Instead of returning a pointer we can build a specific type that keeps a reference to the matrix<br />

and the row index and that provide an operator[] <strong>for</strong> accessing matrix entries. This proxy must<br />

be there<strong>for</strong>e a friend of the matrix class to reach its private data. Alternatively, we can keep<br />

the operator with the parentheses and call this one from the proxy. In both cases, we encounter<br />

cyclic dependencies. 10<br />

If we have several matrix types, each of them would need its own proxy. We would also need<br />

different proxies <strong>for</strong> constant and mutable access respectively. In Section 6.5 we will show how<br />

to write a proxy that works <strong>for</strong> all matrix types. The same templated proxy will handle constant<br />

and mutable access. Fortunately, it even solves the problem of mutual dependencies. The only<br />

minor flaw is that eventual errors cause lenghty compiler messages.<br />

Approach 4: Multi-index type (advanced)<br />

Preliminary note: this approach contains several new language features and discusses some<br />

subtle details. If you do not understand the first time, don’t worry. If you like to skip it, do<br />

it. That will not be a problem <strong>for</strong> understanding the rest of the book. But please read the<br />

comparing discussion.<br />

The fact that operator[] accepts only one argument does not necessarily mean that we cannot<br />

give two. But we need a tricky technique to build one object out of two, without explicitly<br />

constructing the object. The implementation is based on the matrix example from an onlinetutorial<br />

[Sch].<br />

First, we define a type:<br />

struct double index<br />

{<br />

double index (int i1, int i2): i1 (i1), i2 (i2) {}<br />

int i1, i2;<br />

};<br />

For this type we define the access operator:<br />

double& operator[](double index i) { return data[i.i1∗ncols + i.i2]; }<br />

const double& operator[](double index i) const { return data[i.i1∗ncols + i.i2]; }<br />

Now we can write:<br />

A[double index(1, 0)];<br />

This works but it was not the concise notation we were looking <strong>for</strong>.<br />

We introduce a second type:<br />

struct single index<br />

{<br />

single index (int i1): i1 (i1) {}<br />

double index operator, (single index j) const {<br />

10 The dependencies cannot be resolved with <strong>for</strong>ward declaration because we not only define references or<br />

pointers but call member functions in the matrix and in the proxy. We will explain this in § ??.

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!