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