Should the interface use references, constants, and passed values?
! Of course, direct access to class member variables should be avoided as much as possible, because you have no control over the interaction between this member’s state and that of other class members.
Case 1
Take a look at the following call and guess its interface.
ps = read(filename, '\t', maxN, true.false);
Copy the code
You might think of it first
SomeType? read(string? .char.int? .bool.bool);
Copy the code
Look at this definition
vector<Point> read(
std::string const& filename,
char sepaeator = ' '.int maxN = - 1.bool positiveXYonly = false.bool continueOnError = true);
Copy the code
If you want to extend this interface, what do you do? Add an option to read only Points where x<=0 and y<=0
Attempt1:
vector<Point> read(
std::string const& filename,
char sepaeator = ' '.int maxN = - 1.bool positiveXYonly = false.bool negativeXYonly = false.bool continueOnError = true);
//broken legacy calls:. =read(fname, '\t', maxP, true.true); . =read(fname, '\t', maxP, true.false);
Copy the code
Attempt2:
vector<Point> read(
std::string const& filename,
char sepaeator = ' '.int maxN = - 1.bool positiveXYonly = false.bool continueOnError = true.bool negativeXYonly = false.);
//positiveXYonly AND negativeXYonly. =read(fname, '\t', maxP, true.true.true);
Copy the code
this interface is fundamentally broken
- It is difficult to understand
- Difficult to use correctly
- Hardly scalable
To improve the
The function name
ps = read(...). ; vs. ps =readPoints(...). ;Copy the code
-1 is a bad infinity value
vector<Point> readPoints(
std::string const& filename,
char sepaeator = ' '.int maxN = std::numeric_limits<int>::max(),
bool positiveXYonly = false.bool continueOnError = true);
Copy the code
What if I wanted all the 2 to the 64 values? (Replace int if necessary)
vector<Point> readPoints(
std::string const& filename,
char sepaeator = ' '.size_t maxN = std::numeric_limits<size_t>::max(),
bool positiveXYonly = false.bool continueOnError = true);
Copy the code
Get rid of the bool argument
enum class exclude {
none, negativeXY, positiveXY
}
enum class on_error {
continue_reading, stop_reading, empty_result
}
vector<Point> readPoints(
std::string const& filename,
char separator = ' '.size_t maxN = std::numeric_limits<size_t>::max(),
exlude = exclude::none,
on_error = on_error::continue_reading);
Copy the code
The professional type of the separator
class value_separator {
public:
constexper explicit
value_separator(char s = ' ') noexcept:s_{s} {}
constexper char value(a) const noexcept {returns_; }private:
char s_;
}
Copy the code
Limit the number of professional types
class count_limit {
public:
constexper explicit
count_limit(size_t n) noexcept:n_{n} {}
constexper int value(a) const noexcept {returnn_; }static constexper count_limit
none(a) noexpect {
return count_limit{ std::numeric_limits<size_t> : :max()}}private:
size_t n_;
}
Copy the code
So Far
vector<Point> readPoints(
std::string const& filename,
value_separator separator = ' ',
count_limit = count_limit::none(),
exlude = exclude::none,
on_error = on_error::continue_reading); . ps =readPoints(filename,
value_separator{'\t'},
count_limit{maxp},
exlude::negativeXY,
on_error::stop_reading);
Copy the code
Advanced parameters -Points filter
Use STD ::function or template arguments
vector<Point> readPoints(
std::string const& filename,
value_separator separator = ' ', count_limit = count_limit::none(), on_error = on_error::continue_reading, STD ::function<bool(Point const&)> filter = [](Point const&) {return true}); . ps =readPoints(filename,
value_separator{'\t'},
count_limit{maxp},
on_error::stop_reading
[](Point const& p) {
return p.x >= 0 && p.y >= 0;
});
Copy the code
Special SettingsType with special constructs
ps = read_points(filename,
read_settings {
count_limit{maxP},
on_error::stop_reading,
[](ponut const& p) {
return p.x >= 0 && p.y >= 0; }});Copy the code
Separate SettingsType for Settings and Action,
-
Settings cannot be used independently of read operations
-
Multiple reads can be performed without repeatedly specifying Settings
-
Additional states can be carried: the last read operation affects the next
read_settings how;
how.max_count(maxP);
how.filter( [](ponut const& p) {
return p.x >= 0 && p.y >= 0;
});
how.error_action(on_error::stop_reading);
ps = read_points(filename, how);
Copy the code
Case 2
Input: normalized vector (x, y, z) and rotation Angle (a) Output: rotated vector (x, y, z)
quaternion make_screw_rotation (double a, double x, double y, double z);
Copy the code
- Question 1: What are the four parameters? Point of view? Shaft? ->read docs & good luck
- Question 2: Is Angle or radian? ->no way to check
- Q3: Is the axis normalized? -> costly check
- Question 4: Is the result a quaternion quadruple? -> costly check
The order of arguments that the compiler can check
quaternion make_screw_rotation (double angle, vector3d const& axis);
Copy the code
Input constraint type
quaternion make_screw_rotation (radians a, direction3d const& d);
auto d = direction3d{1.0.0.0.1.0};
auto a = degrees{45.0};
auto q = make_screw_rotation(a, d);
template<class Trun>
class angle {. }using degrees = angle< degrees_turn<double> >;
using radians = angle< radians_turn<double> >;
radians a1{ pi / 2 };
degrees a2 = a1;
templates<int dims, class NumT>
class direction {. }using directions3d = direction<3.double>;
directions3d d {1.0.0.0.1.0};
Copy the code