Follow Techotopia on Twitter

On-line Guides
All Guides
eBook Store
iOS / Android
Linux for Beginners
Office Productivity
Linux Installation
Linux Security
Linux Utilities
Linux Virtualization
Linux Kernel
System/Network Admin
Programming
Scripting Languages
Development Tools
Web Development
GUI Toolkits/Desktop
Databases
Mail Systems
openSolaris
Eclipse Documentation
Techotopia.com
Virtuatopia.com
Answertopia.com

How To Guides
Virtualization
General System Admin
Linux Security
Linux Filesystems
Web Servers
Graphics & Desktop
PC Hardware
Windows
Problem Solutions
Privacy Policy

  




 

 

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

Adapter

Adapter takes one type and produces an interface to some other type. This is useful when you re given a library or piece of code that has a particular interface, and you ve got a second library or piece of code that uses the same basic ideas as the first piece, but expresses itself differently. If you adapt the forms of expression to each other, you can rapidly produce a solution.

Suppose you have a generator class that produces Fibonacci numbers:

//: C10:FibonacciGenerator.h
#ifndef FIBONACCIGENERATOR_H
#define FIBONACCIGENERATOR_H
 
class FibonacciGenerator {
int n;
int val[2];
public:
FibonacciGenerator() : n(0) { val[0] = val[1] = 0; }
int operator()() {
int result = n > 2 ? val[0] + val[1] : n > 0 ? 1 : 0;
++n;
val[0] = val[1];
val[1] = result;
return result;
}
int count() { return n; }
};
#endif // FIBONACCIGENERATOR_H ///:~
 

Since it s a generator, you use it by calling the operator( ), like this:

//: C10:FibonacciGeneratorTest.cpp
#include <iostream>
#include "FibonacciGenerator.h"
using namespace std;
 
int main() {
FibonacciGenerator f;
for(int i =0; i < 20; i++)
cout << f.count() << ": " << f() << endl;
} ///:~
 

Perhaps you would like to take this generator and perform STL numeric algorithm operations with it. Unfortunately, the STL algorithms only work with iterators, so you have an interface mismatch. The solution is to create an adapter that will take the FibonacciGenerator and produce an iterator for the STL algorithms to use. Since the numeric algorithms only require an input iterator, the Adapter is fairly straightforward (for something that produces an STL iterator, that is):

//: C10:FibonacciAdapter.cpp
// Adapting an interface to something you already have.
#include <iostream>
#include <numeric>
#include "FibonacciGenerator.h"
#include "../C06/PrintSequence.h"
using namespace std;
 
class FibonacciAdapter { // Produce an iterator
FibonacciGenerator f;
int length;
public:
FibonacciAdapter(int size) : length(size) {}
class iterator;
friend class iterator;
class iterator : public std::iterator<
std::input_iterator_tag, FibonacciAdapter, ptrdiff_t> {
FibonacciAdapter& ap;
public:
typedef int value_type;
iterator(FibonacciAdapter& a) : ap(a) {}
bool operator==(const iterator&) const {
return ap.f.count() == ap.length;
}
bool operator!=(const iterator& x) const {
return !(*this == x);
}
int operator*() const { return ap.f(); }
iterator& operator++() { return *this; }
iterator operator++(int) { return *this; }
};
iterator begin() { return iterator(*this); }
iterator end() { return iterator(*this); }
};
 
int main() {
const int SZ = 20;
FibonacciAdapter a1(SZ);
cout << "accumulate: "
<< accumulate(a1.begin(), a1.end(), 0) << endl;
FibonacciAdapter a2(SZ), a3(SZ);
cout << "inner product: "
<< inner_product(a2.begin(), a2.end(), a3.begin(), 0)
<< endl;
FibonacciAdapter a4(SZ);
int r1[SZ] = {0};
int* end = partial_sum(a4.begin(), a4.end(), r1);
print(r1, end, "partial_sum", " ");
FibonacciAdapter a5(SZ);
int r2[SZ] = {0};
end = adjacent_difference(a5.begin(), a5.end(), r2);
print(r2, end, "adjacent_difference", " ");
} ///:~
 

You initialize a FibonacciAdapter by telling it how long the Fibonacci sequence can be. When an iterator is created, it simply captures a reference to the containing FibonacciAdapter so that it can access the FibonacciGenerator and length. Note that the equivalence comparison ignores the right-hand value because the only important issue is whether the generator has reached its length. In addition, the operator++( ) doesn t modify the iterator; the only operation that changes the state of the FibonacciAdapter is calling the generator function operator( ) on the FibonacciGenerator. We can get away with this extremely simple version of the iterator because the constraints on an Input Iterator are so strong; in particular, you can only read each value in the sequence once.

In main( ), you can see that all four different types of numeric algorithms are successfully tested with the FibonacciAdapter.

Thinking in C++ Vol 2 - Practical Programming
Prev Home Next

 
 
   Reproduced courtesy of Bruce Eckel, MindView, Inc. Design by Interspire