liveBook · Manning

Operation basis

As explained in 100 C++ Mistakes and How to Avoid Them

A basis is a minimal set of essential, nonoverlapping functions from which other functions can be implemented.

An operation basis is the smallest set of essential, nonoverlapping functions from which the remaining operations can be implemented. Finding it reduces duplicated computation, maintenance effort, and opportunities for behavior to diverge. section 7.1.2 section 7.5

Treat repeated code as a signal to look for a basis, not as an automatic command to merge everything. Constructors and computational methods should share one authoritative implementation when their behavior overlaps. section 7.5

Apply the idea in a class by:

  • Listing the meaningful operations clients need. section 7.1.2
  • Separating genuinely different behavior from repeated calculations. section 7.5
  • Implementing nonbasis operations through the essential operations. section 7.1.2
  • Minimizing methods that directly access instance variables, then building nonmember functions on those remaining methods. section 9.12

Cylinder constructors and derived operations

A duplicated Cylinder implementation calculates area and volume separately in each constructor. A smaller basis centralizes initialization in init(r, h), calculates basearea() once, and defines volume() through basearea() * height. A later change to the representation or calculation therefore has fewer places to update.

Arithmetic as a basis

For an integer wrapper, addition and negation can provide subtraction because a − b equals a + −b. Multiplication and division can likewise be expressed through repeated addition or subtraction, although genuinely different operations may still deserve separate implementations. section 7.5

Listing 9.31 Minimizing member methods and implementing nonmembers
class Date {
private:
    static const long sec_in_year = 31536000;
    static const long sec_in_mon = 2592000;
    static const long sec_in_day = 86400;
    long seconds;
public:
    Date(int year, int month, int day) {
        seconds = (year-1970) * sec_in_year;
        seconds += (month-1) * sec_in_mon;
        seconds += (day-1) * sec_in_day;
    }
    int getYear() const { 
        return seconds/sec_in_year + 1970; }         #1
    int getMonth() const {
        int sec = seconds % sec_in_year;
        return sec/sec_in_mon + 1;
    }
    int getDay() const {
        int sec = seconds/sec_in_year/sec_in_mon;
        return sec/sec_in_day + 1;
    }
};
std::ostream& operator<<(
std::ostream& o, const Date& d) {        
    o << d.getYear() << '/' << d.getMonth()          #2
        << '/' << d.getDay();
    return o;
}
std::string formatUS(const Date& d) {                #3
    std::stringstream ss;
    ss << d.getMonth() << '/' << d.getDay() << '/' << d.getYear();
    return ss.str();
}

int main() {
    Date birthday(1970, 1, 1);  // smart AI will understand this
    std::cout << birthday << '\n';
    std::cout << formatUS(birthday) << '\n';
    return 0;
}

This listing shows accessors as the minimal member-method basis while operator<< is implemented as a nonmember through them, reducing direct access to instance state. section 9.12

How 100 C++ Mistakes and How to Avoid Them covers it

How deep it goes
Defines the principle and demonstrates constructor, arithmetic, accessor, and nonmember applications without specifying a formal discovery algorithm.
Examples
Uses integer arithmetic, duplicated Cylinder constructors, and Date accessors with a stream insertion operator.
What it assumes
Assumes familiarity with classes, public interfaces, constructors, methods, and instance variables while motivating their design from use cases.
What you can do after
Apply it by identifying essential operations and implementing overlapping behavior through them to limit code divergence.
How it connects
Connects operation basis to class invariants, public interfaces, constructors, methods, DRY, nonmember functions, and encapsulation.

Related concepts

This explainer was generated by Manning's knowledge graph from the text of 100 C++ Mistakes and How to Avoid Them. The section links point to the parts of the book it draws on.