Encapsulating a large number of parameters in C ++ 14

I want to write a function that uses a lot of parameters, which I will call a, band c. I have four options for implementing this in C ++ 14.

For the new modern C ++ project in 2018, which of these styles best adheres to the ISO C ++ philosophy ? What 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 understand.

Minuses:

  • To figure things out in map or fold operations, we have to make a clumsy [computer](int input){ return computer.compute(input); }

Style C

struct ComputeParams {
    int a, b, c;
};

int compute(const ComputeParams &params, 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

Minuses:

  • Verbal implementation computeincludes a call params.ainstead a.
  • Conditional calls must go through each time in the structure.

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);

:

  • - ,
  • , map, fold for_each

:

  • "" .

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);

:

  • OCaml
  • , map, fold for_each
  • ,

:

  • ++ C,
  • - , , auto - std::function
  • vtables
+6
3

: /

std::function<int(int)> getCompute(int a, int b, int c)
{
    if(a==0)
        return [b,c](int input) { /* version for a=0 */ };
    if(b==0)
        return [a,c](int input) { /* version for b=0 */ };
    if(c==0)
        return [a,b](int input) { /* version for c=0 */ };
    /* more optimized versions */
    return [a,b,c](int input) { /* general version */ };
}

- . , std::function .

+4

, .

-

. , , compute, operator () . operator () , algorithm, Functor Functional.

, , . , , ( LLVM/Clang) , ( 1:32:37, ). , , / .

C

API. , struct, , , (, algorithm). , , struct, , .

, , . , , , - , , ( ). C++ , /, , , :).

, , Cppcon, , / . ++ , .

+2

tl; dr: .

-

-, . , " - b c", , ; a, a b c.

Functor

, - . .

... , :

C- -

++. - - .

, , :

struct ComputeParams {
    int a, b, c;
};

auto compute(ComputeParams params, int input) {
    auto [a, b, c] = params;
    // do something with a, b and c
}
auto result = compute(ComputeParams{a, b, c}, 123);

This is valid with C ++ 17 (using structured binding); in C ++ 14 you will need std::tieto bind parameters to local names. Also, note that I use more value semantics than reference semantics, letting the compiler do its magic (which is likely to happen even if it doesn't really matter for multiple ints).

This is what I would recommend.

+2
source

All Articles