Operator Overloading and Generic ProgrammingIntroductionMechatronics software frequently manipulates objects that represent physical quantities, geometric entities, sensor readings, configurations, and control states. A two-dimensional position, for example, is more meaningful as an object than as two unrelated floating-point variables. Similarly, a matrix, unit-bearing measurement, trajectory, or robot pose should support operations that resemble its mathematical or engineering meaning. C++ supports this style through operator overloading. It also provides generic programming, in which algorithms and data structures are written once and then used with many types. Function templates, class templates, specialization, concepts, and type traits allow programmers to express reusable abstractions while retaining compile-time type checking and performance. These facilities are powerful but require disciplined design. An overloaded operator should preserve intuitive meaning, templates should state their requirements clearly, and generic code should avoid assuming properties that have not been established. This chapter develops those principles through examples relevant to engineering software. Learning ObjectivesAfter completing this chapter, students should be able to: - Explain the purpose, syntax, and constraints of overloaded operators.
- Design value types with appropriate arithmetic, comparison, and stream operators.
- Distinguish member, non-member, and friend operator implementations.
- Write function and class templates for reusable algorithms and data structures.
- Apply specialization, type traits,
if constexpr, and concepts appropriately. - Identify common generic-programming errors involving ownership, conversions, constraints, and efficiency.
- Evaluate an engineering design involving overloaded operators and templates.
1. Operator Overloading as a Value-Type InterfaceAn operator is overloaded when a programmer defines how an existing C++ operator behaves for a user-defined type. For example, if Vector2 represents a planar vector, the expression a + b can be made to represent vector addition. #include <iostream>
struct Vector2 {
double x{};
double y{};
Vector2 operator+(const Vector2& other) const {
return {x + other.x, y + other.y};
}
};The expression a + b is translated conceptually into a.operator+(b) when a member overload is selected. Operator overloading does not create new operators. It only provides a meaning for an existing operator when at least one operand is a class, enumeration, or related user-defined type. 1.1 Appropriate semanticsA good overloaded operator has a meaning consistent with ordinary usage. For a value type, the following are often natural: + and -: combine or subtract values.- Unary
-: reverse a value or direction. * and /: scale by a scalar, where that meaning is established.== and !=: compare value equality.<=>: provide three-way comparison when ordering is meaningful.[]: access an indexed element.() : invoke a function object or callable object.<< and >>: formatted output and input for streams.
An operator should not be overloaded merely because a shorter expression is possible. For example, using + to mean “send a command to a motor” would violate user expectations and make code harder to review. 1.2 Operators cannot change fundamental rulesOverloading cannot change an operator’s precedence, number of operands, or associativity. It also cannot introduce an operator such as **. Some operators must be non-static member functions, including assignment =, subscript [], function call (), and member access ->. Operators such as + may be implemented as members or non-members. An overloaded operator is still a function. It may have parameters, a return type, const qualification, and exception specifications. The implementation should preserve the normal algebraic expectations where they apply. For example, vector addition should be commutative, while matrix multiplication generally is not. 2. Designing a Robust Value TypeA value type is an object whose identity is determined primarily by its stored value. It can be copied, compared, and passed to functions without sharing mutable ownership. Examples include angles, positions, colors, and calibration coefficients. Consider a two-dimensional vector with arithmetic and equality operations: #include <cmath>
class Vector2 {
public:
constexpr Vector2() = default;
constexpr Vector2(double x_value, double y_value)
: x_(x_value), y_(y_value) {}
constexpr double x() const noexcept { return x_; }
constexpr double y() const noexcept { return y_; }
constexpr Vector2& operator+=(const Vector2& rhs) noexcept {
x_ += rhs.x_;
y_ += rhs.y_;
return *this;
}
constexpr Vector2& operator-=(const Vector2& rhs) noexcept {
x_ -= rhs.x_;
y_ -= rhs.y_;
return *this;
}
constexpr Vector2& operator*=(double scalar) noexcept {
x_ *= scalar;
y_ *= scalar;
return *this;
}
friend constexpr Vector2 operator+(Vector2 left,
const Vector2& right) noexcept {
left += right;
return left;
}
friend constexpr Vector2 operator-(Vector2 left,
const Vector2& right) noexcept {
left -= right;
return left;
}
friend constexpr Vector2 operator*(Vector2 value,
double scalar) noexcept {
value *= scalar;
return value;
}
friend constexpr Vector2 operator*(double scalar,
Vector2 value) noexcept {
value *= scalar;
return value;
}
friend constexpr bool operator==(const Vector2&, const Vector2&) = default;
private:
double x_{0.0};
double y_{0.0};
};The compound assignment operators implement the modification. The binary operators then copy the left operand, modify the copy, and return it. This avoids duplicating arithmetic logic. Passing the left operand by value is intentional: it creates a copy for the result and permits efficient move behavior in more complex types. The constexpr specifier permits evaluation at compile time when the arguments are constant expressions. noexcept documents that these operations are not expected to throw. Such specifications improve optimization and help generic code make decisions about exception safety. 2.1 Floating-point equalityThe defaulted equality operation compares double members exactly. This is appropriate only when exact representation is intended. Calculations involving measurement or repeated arithmetic often require a tolerance-based comparison: bool approximately_equal(Vector2 a, Vector2 b,
double tolerance = 1e-9) {
return std::abs(a.x() - b.x()) <= tolerance &&
std::abs(a.y() - b.y()) <= tolerance;
}The tolerance must be selected according to scale, sensor uncertainty, and numerical conditioning. A fixed absolute tolerance may be unsuitable when values vary greatly in magnitude; a combined absolute-relative criterion may be preferable. Approximate equality should not automatically replace exact operator==, because approximate relations may fail to have the transitivity expected by ordered containers and algorithms. 2.2 Symmetry and non-member operatorsScalar multiplication should normally support both v s and s v. A non-member overload makes both operand orders possible. Non-member operators are also useful when implicit conversions should apply to both operands. If private access is required, a friend declaration can grant access, but friendship should be limited to the operations that need it. 2.3 Stream operatorsStream insertion is conventionally a non-member function because the left operand is the stream: #include <ostream>
std::ostream& operator<<(std::ostream& out, const Vector2& value) {
return out << '(' << value.x() << ", " << value.y() << ')';
}Returning the stream by reference permits chaining such as std::cout << a << b. Formatting is an interface decision: diagnostic output, serialization, and machine-readable interchange may require separate functions rather than one overloaded stream representation. 3. Comparison and Three-Way OrderingC++20 introduced the three-way comparison operator, commonly called the spaceship operator, <=>. It can generate relational operations when an ordering is meaningful. #include <compare>
struct Version {
int major;
int minor;
int patch;
auto operator<=>(const Version&) const = default;
};The generated comparison is lexicographical: major is compared first, then minor, then patch. This is suitable for versions. It is not automatically suitable for physical vectors, because there is no universally meaningful “less than” relation between two planar directions. Ordering floating-point values requires care because NaN values do not participate in an ordinary total order. A type intended for ordered containers must supply a comparison consistent with the container’s ordering requirements. Equality, equivalence, and numerical closeness are distinct concepts. 4. Conversion Operators and ExplicitnessA conversion operator defines how an object converts to another type: class Angle {
public:
explicit Angle(double radians) : radians_(radians) {}
explicit operator double() const noexcept { return radians_; }
private:
double radians_;
};explicit prevents accidental conversions in unrelated expressions. This is especially important for physical quantities. An implicit conversion from an angle to double could permit a value in radians to be passed where a dimensionless coefficient is expected. Explicit conversions make unit boundaries visible in the source code.
Constructors taking one argument can also act as conversion constructors. They should generally be explicit unless implicit conversion is genuinely safe and unsurprising. 5. Function TemplatesA function template describes an algorithm in terms of one or more types: template <typename T>
T maximum(T a, T b) {
return (a < b) ? b : a;
}When the function is called, the compiler deduces T from the arguments and generates an appropriate specialization. The template does not require a common base class. Instead, it requires that the operations used in its body are valid for the selected type. This is often called duck typing at compile time. Template argument deduction is sensitive to references and cv-qualifiers. A parameter of type T usually copies and may remove top-level references and qualifiers. A parameter of type const T& can bind to lvalues and rvalues without copying. A parameter of type T&& may be a forwarding reference when T is deduced, allowing preservation of value category with std::forward. A generic accumulation function illustrates an important design choice: #include <iterator>
template <typename InputIt, typename T>
T sum(InputIt first, InputIt last, T initial) {
for (; first != last; ++first) {
initial = initial + *first;
}
return initial;
}This algorithm does not require the element type and accumulator type to be identical. A sequence of integers can be accumulated into a wider integer or floating-point type. The operation must nevertheless be valid, and the initial value establishes the result type. 6. Class TemplatesA class template defines a family of related types. The following fixed-size buffer stores its elements directly: #include <cstddef>
#include <stdexcept>
template <typename T, std::size_t N>
class Buffer {
public:
constexpr std::size_t size() const noexcept { return N; }
T& operator[](std::size_t index) noexcept {
return data_[index];
}
const T& operator[](std::size_t index) const noexcept {
return data_[index];
}
private:
T data_[N]{};
};N is a non-type template parameter. Consequently, the size is known at compile time and can be used in type checking and storage layout. operator[] is intentionally unchecked, matching the conventional semantics of built-in arrays. A separate at() function could perform bounds checking and throw an exception or use an alternative error policy.
A class template may have default template arguments, static members, nested types, and member functions that are themselves templates. Generic containers should document ownership, copying, exception behavior, iterator validity, and complexity. 7. Specialization and CustomizationA primary template gives the general implementation. A specialization supplies a different implementation for a particular type or pattern. template <typename T>
struct TypeName {
static constexpr const char* value = "unknown";
};
template <>
struct TypeName<int> {
static constexpr const char* value = "integer";
};This is full specialization. A partial specialization matches a family of types: template <typename T>
struct IsPointer {
static constexpr bool value = false;
};
template <typename T>
struct IsPointer<T*> {
static constexpr bool value = true;
};Specialization should represent a real semantic or implementation distinction. Excessive specialization makes a library difficult to understand and can create surprising interactions. In modern C++, concepts and if constexpr often express conditional behavior more clearly than large collections of partial specializations. 8. Type Traits and Compile-Time DecisionsType traits are compile-time templates that report or transform type properties. The standard library provides traits such as std::is_integral_v<T>, std::is_floating_point_v<T>, std::is_same_v<T, U>, and std::remove_reference_t<T>. #include <type_traits>
template <typename T>
auto square(T value) {
static_assert(std::is_arithmetic_v<T>,
"square requires an arithmetic type");
return value * value;
}static_assert turns an invalid use into a compile-time diagnostic. It is preferable to allowing a distant and confusing error from a failed expression.
if constexpr discards the branch that is not selected during instantiation:
#include <string>
template <typename T>
std::string describe(const T& value) {
if constexpr (std::is_arithmetic_v<T>) {
return "numeric value: " + std::to_string(value);
} else {
return "non-numeric value";
}
}Unlike an ordinary if, the discarded branch need not be valid for the selected type, provided that it is not invalid for every possible instantiation in a way prohibited by the language rules. 9. Concepts: Expressing Generic RequirementsTemplates traditionally report errors only after substitution fails. C++20 concepts allow a programmer to state requirements directly. #include <concepts>
template <typename T>
concept Addable = requires(T a, T b) {
{ a + b } -> std::convertible_to<T>;
};
template <Addable T>
T combine(T a, T b) {
return a + b;
}The requires expression checks whether the expression is valid and whether its result satisfies a further constraint. A concept documents the intended interface and usually produces clearer diagnostics. The standard library supplies concepts including std::integral, std::floating_point, std::same_as, std::convertible_to, and iterator-related concepts. A domain-specific concept can be more meaningful than a broad standard concept: template <typename T>
concept StateLike = requires(const T& state) {
{ state.position() } -> std::convertible_to<double>;
{ state.velocity() } -> std::convertible_to<double>;
};Concepts do not prove that an operation is physically meaningful. They establish syntactic and declared semantic requirements. The programmer must still ensure that units, ranges, invariants, and numerical assumptions are correct. 10. Generic Design Principles10.1 Separate interface from implementationA generic algorithm should state what it needs rather than how a particular type is represented. For example, an algorithm that needs iteration should use iterators or ranges rather than assuming an array member. 10.2 Prefer the weakest sufficient requirementIf an algorithm only reads elements, it should accept input iterators rather than requiring random access. Weaker requirements increase reuse. Conversely, falsely weak requirements lead to invalid assumptions; a binary-search algorithm genuinely requires a sorted range and efficient advancement. 10.3 Preserve invariantsA generic class representing a measurement should not permit operations that produce incompatible units. A matrix class should establish dimensions and define whether multiplication is checked at compile time or run time. Genericity must not remove domain rules. 10.4 Avoid unnecessary copiesUse const T& for read-only objects when copying is expensive, pass small trivially copied values by value, and use forwarding references only when forwarding is actually required. Premature forwarding can make interfaces harder to understand. 10.5 Prefer composition over clever metaprogrammingReadable templates are easier to test and maintain. Concepts, small helper functions, and standard library algorithms are generally preferable to deeply recursive metaprogramming. 10.6 Consider complexity and exception safetyA generic operation should document its time and space complexity. It should also preserve object invariants if an exception occurs. For example, a container insertion should provide a clearly stated basic, strong, or nothrow exception guarantee when practical. 11. Worked Example: A Generic PID ComponentA proportional-integral-derivative controller can be represented conceptually by e(t) = r(t) − y(t) where e(t) is the error, r(t) is the reference, and y(t) is the measured output. A continuous controller is often written as u(t) = Kp e(t) + Ki ∫₀ᵗ e(τ)dτ + Kd de(t)/dt Here, u(t) is the control signal; K_p, K_i, and K_d are proportional, integral, and derivative gains. This equation assumes a continuous-time model and ideal differentiation. A digital implementation must use a sampling interval and numerical approximations; it is not identical to the continuous expression. A simple discrete implementation can use Ik = Ik−1 + ek ∆t and Dk = (ek − ek−1) / ∆t where ∆t > 0 is the sampling interval. The control output is then u_k = K_p e_k + K_i I_k + K_d D_k. These formulas assume a fixed or known positive sampling interval and do not by themselves address actuator saturation, derivative noise, or anti-windup. A reusable scalar template is: template <std::floating_point T>
class PID {
public:
PID(T kp, T ki, T kd) : kp_(kp), ki_(ki), kd_(kd) {}
T update(T reference, T measurement, T dt) {
if (!(dt > T{0})) {
throw std::invalid_argument("dt must be positive");
}
const T error = reference - measurement;
integral_ += error * dt;
const T derivative = (error - previous_error_) / dt;
previous_error_ = error;
return kp_ * error + ki_ * integral_ + kd_ * derivative;
}
void reset() noexcept {
integral_ = T{};
previous_error_ = T{};
}
private:
T kp_, ki_, kd_;
T integral_{};
T previous_error_{};
};This example uses the std::floating_point concept because the implementation assumes fractional arithmetic. The dt check protects a mathematical precondition. A production controller would normally add output limits, integral clamping or back-calculation anti-windup, derivative filtering, and a clearly specified behavior after missed samples. The example also demonstrates an important boundary: generic programming can abstract the numeric type, but it cannot automatically determine suitable gains or guarantee closed-loop stability. Those remain control-engineering responsibilities. 12. Case Study: Generic Pose and Sensor ProcessingBackgroundConsider an illustrative mobile-robot project. The robot receives wheel odometry, an inertial measurement unit, and a target pose. The original prototype represents positions using raw arrays and mixes metres, degrees, and radians. Bugs occur when a sensor value is passed to a function expecting a different unit. ProblemThe team needs reusable operations for two-dimensional positions and velocities, compile-time-friendly processing of sensor samples, and readable diagnostics. The design must avoid dynamic allocation in the control loop and must make invalid combinations difficult to express. AnalysisA Vector2 value type can provide addition, subtraction, and scalar multiplication. A separate Angle type can prevent accidental mixing of angular and linear quantities. A generic filtering algorithm can operate on any range whose elements satisfy the required operations. Concepts can communicate these requirements without requiring inheritance. The team decides not to define an ordering for Vector2, because “less than” has no domain meaning. It defines exact equality for structural tests and a separately named approximate comparison for numerical validation. Stream insertion is used only for diagnostics; a dedicated serialization function is used for communication packets. Approach and solutionThe implementation uses: - value semantics for positions and velocities;
constexpr and noexcept where justified;- non-member symmetric arithmetic operators;
- explicit unit conversions;
- a fixed-size
Buffer<T, N> for bounded samples; - a constrained generic mean function for numeric samples;
- unit tests for zero, identity, boundary, and invalid cases.
A mean function might be written as: template <std::floating_point T, std::size_t N>
T mean(const Buffer<T, N>& values) {
static_assert(N > 0, "mean requires at least one value");
T total{};
for (std::size_t i = 0; i < N; ++i) {
total += values[i];
}
return total / static_cast<T>(N);
}The compile-time assertion prevents division by zero for an empty fixed-size buffer. The function is appropriate for arithmetic sample values, but a real sensor pipeline must also address outliers, missing samples, timestamp alignment, and uncertainty. OutcomeThe resulting code is easier to read because expressions resemble the domain model. Invalid uses produce earlier compiler diagnostics, and the controller loop has predictable storage behavior. The separation between mathematical value operations and communication serialization also reduces accidental interface coupling. Learning points- Natural syntax is valuable only when the operation has clear semantics.
- Concepts improve diagnostics but do not validate physical correctness.
- Unit safety is often better achieved through distinct types than comments.
- Approximate numerical comparison should be named explicitly.
- Generic abstractions must be evaluated for memory, timing, and failure behavior in embedded systems.
13. Common Errors and LimitationsReturning a reference to a temporary. An operator returning a reference must refer to an object whose lifetime continues. Value-producing arithmetic should normally return by value. Making every operator a member. This can prevent symmetric conversions and expressions such as scalar * vector. Overloading &&, ||, or the comma operator carelessly. Overloaded logical operators do not preserve built-in short-circuit behavior. Such overloads can produce surprising side effects. Using approximate equality as an ordering. Tolerance-based relations may violate strict weak ordering and should not be used casually as keys in ordered containers. Unconstrained templates. A template that assumes x.size(), x + y, and x.value() without stating requirements produces poor diagnostics. Concepts or targeted static_assert statements improve the interface. Specializing standard-library templates improperly. User code may generally add permitted specializations only under strict rules, and adding arbitrary specializations can cause undefined behavior or portability problems. Prefer user-defined customization points or overloads. Ignoring ownership. A generic class holding a raw pointer must define ownership, copying, moving, and destruction correctly. Standard containers and smart pointers are usually safer foundations. Confusing compile-time and run-time validation. A matrix dimension known through template parameters can be checked during compilation, while dimensions read from a file require run-time checks. Both forms may be necessary. 14. Best Practices and Contemporary C++Use modern standard-library facilities such as concepts, ranges, std::array, std::span, and algorithms where they clarify intent. std::span is useful for a non-owning view of contiguous data, but its lifetime must not exceed the referenced storage. Ranges can make generic pipelines expressive, but embedded projects should still assess generated code, allocation, timing, and toolchain support. Treat compiler diagnostics as part of the user experience of a template library. Give concepts meaningful names and write constraints close to the interface. Test templates with representative types, including small scalar types, user-defined value types, const objects, move-only objects, and boundary cases. In safety-related mechatronic systems, operator overloading and templates do not replace requirements engineering, code review, static analysis, hardware-in-the-loop testing, or applicable functional-safety processes. Generic code can reduce duplication, but an error in a widely reused abstraction can affect many subsystems. Traceability, version control, deterministic behavior, and documented assumptions remain essential. Chapter SummaryOperator overloading allows user-defined value types to provide interfaces that resemble their mathematical or engineering meaning. Good overloads are predictable, preserve domain semantics, and use appropriate return types, const qualifications, exception specifications, and conversion rules. Compound assignment operators can centralize implementation, while non-member functions support symmetry. Function and class templates provide reusable compile-time abstractions. Type deduction, specialization, type traits, if constexpr, and concepts determine how generic code is selected and constrained. Concepts improve documentation and diagnostics, but they cannot establish physical validity or numerical stability by themselves. Effective generic design uses the weakest sufficient requirements, preserves invariants, controls ownership and lifetime, documents complexity, and considers exception safety and embedded-system constraints. In mechatronics, these techniques support readable vector, pose, sensor, controller, and fixed-size data abstractions while maintaining compile-time checking and predictable performance. Key TermsOperator overloading: Defining an existing C++ operator for a user-defined type. Value type: A type whose identity is primarily determined by its stored value. Member operator: An operator implemented as a member function of a class. Non-member operator: An operator implemented as a free function. Friend function: A non-member function granted access to a class’s private members. Compound assignment: An operator such as += that modifies its left operand. Conversion operator: A member function specifying conversion to another type. Function template: A parameterized function definition that supports multiple types. Class template: A parameterized class definition that produces a family of types. Template argument deduction: Compiler inference of template parameters from function arguments. Full specialization: A custom template implementation for one exact set of arguments. Partial specialization: A custom implementation matching a family of template arguments. Type trait: A compile-time template that reports or transforms a type property. if constexpr: A compile-time conditional whose inactive branch is discarded.
Concept: A named compile-time requirement on template arguments. Constraint: A condition limiting which template arguments are acceptable. Strict weak ordering: An ordering relation suitable for many standard ordered algorithms and containers. constexpr: A declaration permitting evaluation during compilation when conditions allow.
Exception guarantee: A specification of object behavior if an operation throws. Generic programming: Designing algorithms and data structures reusable across types through common requirements. Review QuestionsShort Answer Questions- What is operator overloading, and what aspects of an operator can it not change?
- Why are symmetric arithmetic operators often implemented as non-member functions?
- Distinguish a full specialization from a partial specialization.
- What problem do C++ concepts address in template programming?
- Why should approximate floating-point equality usually be separate from
operator==?
Long Answer Questions- Explain how to design a robust value type for a two-dimensional vector. Discuss arithmetic operators, equality, stream output,
const, constexpr, and noexcept. - Compare unconstrained templates, type traits with
static_assert, and concepts. Discuss diagnostics, readability, and applicability. - Explain how class templates and non-type template parameters can support fixed-size data structures in embedded mechatronics software.
- Discuss conversion constructors and conversion operators, including why explicit conversions are important for unit-bearing engineering quantities.
- Describe the major generic-programming design principles that control requirements, ownership, complexity, exception safety, and maintainability.
Analytical / Application Questions- A robot software library defines
operator< for Vector2 by comparing only the x-coordinate. Analyze why this may be misleading and propose a better interface. - Design a constrained generic function that computes the average of a fixed-size sequence of floating-point sensor samples. State its assumptions and identify at least three production issues not solved by the function.
- A PID template accepts any arithmetic type and permits
dt == 0. Analyze the numerical and software risks, then propose improvements for a production embedded controller.
Multiple Choice Questions with AnswersQuestion 1Which statement best describes operator overloading in C++? A. It creates entirely new operators with arbitrary precedence. B. It defines the behavior of existing operators for user-defined types. C. It allows operators to have any number of operands. D. It changes the associativity of built-in operators. Correct Answer: B. It defines the behavior of existing operators for user-defined types. Question 2Why is scalar multiplication for a vector commonly implemented as a non-member operator? A. Only non-members can return objects by value. B. Non-members automatically make multiplication run at compile time. C. It can support both vector scalar and scalar vector symmetrically. D. Member operators cannot accept scalar arguments. Correct Answer: C. It can support both vector scalar and scalar vector symmetrically. Question 3What is the main purpose of the explicit keyword on a single-argument constructor? A. To prevent unintended implicit conversions. B. To force dynamic allocation. C. To make the constructor private. D. To enable inheritance automatically. Correct Answer: A. To prevent unintended implicit conversions. Question 4What does a non-type template parameter such as std::size_t N provide in Buffer<T, N>? A. A run-time value stored on the heap. B. A compile-time value that can influence the type and storage size. C. A virtual function table size. D. A replacement for all type parameters. Correct Answer: B. A compile-time value that can influence the type and storage size. Question 5Which feature is designed to express requirements on template arguments directly? A. Namespaces B. Concepts C. Friend declarations D. Stream insertion Correct Answer: B. Concepts Question 6Why can approximate equality be unsuitable for ordered containers? A. It always requires dynamic memory. B. It may fail to provide the consistency required of an ordering relation. C. It cannot compare floating-point values. D. It changes an object’s ownership. Correct Answer: B. It may fail to provide the consistency required of an ordering relation. Question 7What does if constexpr do in a template? A. It evaluates both branches at run time. B. It discards the branch not selected at compile time. C. It converts all arguments to constexpr objects. D. It specializes every class in the program. Correct Answer: B. It discards the branch not selected at compile time. Question 8For the discrete PID expression D_k = (e_k − e_{k−1}) / ∆t, which condition is required? A. ∆t must be zero. B. ∆t must be negative. C. ∆t must be positive and nonzero. D. e_k must always equal e_{k−1}. Correct Answer: C. ∆t must be positive and nonzero. Question 9Which implementation is conventional for stream insertion of a value type? A. A non-member returning the stream by reference. B. A destructor returning a stream by value. C. A private data member named operator<<. D. A conversion from the stream to the value type. Correct Answer: A. A non-member returning the stream by reference. Question 10What is a principal benefit of using the weakest sufficient generic requirement? A. It makes every algorithm use inheritance. B. It increases the number of unnecessary copies. C. It allows an algorithm to work with more types while preserving its assumptions. D. It guarantees physical correctness of all supplied values. Correct Answer: C. It allows an algorithm to work with more types while preserving its assumptions.
|