I want to write a function which uses many parameters, which I will call a
, b
, and c
. I have four choices of implementing this in C++14.
For a new modern C++ project in 2018, which one of these styles best adheres to the philosophy of the ISO C++? Which styles are recommended by other style guides?
Object oriented style
class Computer {
int a, b, c;
public:
Computer(int a, int b, int c) : a(a), b(b), c(c) {}
int compute(int) const {
// do something with a, b, c
}
};
...
const Computer computer(a, b, c);
int result = computer.compute(123);
Pros:
- Easy for C++ programmers to grasp
Cons:
- To compute things in map or fold operations, we have to do the clunky
[computer](int input){ return computer.compute(input); }
C style
struct ComputeParams {
int a, b, c;
};
int compute(const ComputeParams ¶ms, int input) {
// do something with params.a, params.b, params.c
}
...
const ComputeParams params{a, b, c};
int result = compute(params, 123);
Pros:
- Easy for C programmers to grasp
Cons:
- Verbose implementation of
compute
involves callingparams.a
instead ofa
. - Verbose calling, have to pass in a struct every time.
Functor style
struct Computor {
int a, b, c;
int operator()(int input) const {
// do something with a, b, c
}
};
...
const Computor compute{a, b, c};
int result = compute(123);
Pros:
- All the advantages of object oriented style, plus it looks like a function
- Can use in functional operations such as map, fold, and for_each
Cons:
- The word "functor" looks funky.
Functional style
auto genCompute(int a, int b, int c) {
return [a, b, c](int input) -> int {
// do something with a, b, c
}
}
...
auto compute = genCompute(a, b, c);
int result = compute(123);
Pros:
- Easy for OCaml programmers to grasp
- Can use in functional operations such as map, fold, and for_each
- Technically the same as a functor
Cons:
- Hard for C++ and C programmers to grasp
- Since lambda functions are a unique type that's generated by the compiler, may require use of
auto
or template magic to inline the lambda function, orstd::function
with a performance overhead - Can't embrace the power of vtables and inheritance for polymorphism