Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
CPlusPlusNotesForProfessionals.pdf
Скачиваний:
47
Добавлен:
20.05.2023
Размер:
5.11 Mб
Скачать

e = a * b; f = a / b;

}

Pointers:

void calculate(int a, int b, int* c, int* d, int* e, int* f) { *c = a + b;

*d = a - b; *e = a * b; *f = a / b;

}

Some libraries or frameworks use an empty 'OUT' #define to make it abundantly obvious which parameters are output parameters in the function signature. This has no functional impact, and will be compiled out, but makes the function signature a bit clearer;

#define OUT

void calculate(int a, int b, OUT int& c) { c = a + b;

}

Section 24.5: Using a Function Object Consumer

We can provide a consumer that will be called with the multiple relevant values:

Version ≥ C++11

template <class F>

void foo(int a, int b, F consumer) { consumer(a + b, a - b, a * b, a / b);

}

// use is simple... ignoring some results is possible as well foo(5, 12, [](int sum, int , int , int ){

std::cout << "sum is " << sum << '\n';

});

This is known as "continuation passing style".

You can adapt a function returning a tuple into a continuation passing style function via:

Version ≥ C++17

template<class Tuple> struct continuation {

Tuple t; template<class F>

decltype(auto) operator->*(F&& f)&&{

return std::apply( std::forward<F>(f), std::move(t) );

}

};

std::tuple<int,int,int,int> foo(int a, int b);

continuation(foo(5,12))->*[](int sum, auto&&...) { std::cout << "sum is " << sum << '\n';

};

with more complex versions being writable in C++14 or C++11.

GoalKicker.com – C++ Notes for Professionals

126

Section 24.6: Using std::pair

The struct template std::pair can bundle together exactly two return values, of any two types:

#include <utility>

std::pair<int, int> foo(int a, int b) { return std::make_pair(a+b, a-b);

}

With C++11 or later, an initializer list can be used instead of std::make_pair:

Version ≥ C++11

#include <utility>

std::pair<int, int> foo(int a, int b) { return {a+b, a-b};

}

The individual values of the returned std::pair can be retrieved by using the pair's first and second member objects:

std::pair<int, int> mrvs = foo(5, 12);

std::cout << mrvs.first + mrvs.second << std::endl;

Output:

10

Section 24.7: Using std::array

Version ≥ C++11

The container std::array can bundle together a fixed number of return values. This number has to be known at compile-time and all return values have to be of the same type:

std::array<int, 4> bar(int a, int b) { return { a + b, a - b, a * b, a / b };

}

This replaces c style arrays of the form int bar[4]. The advantage being that various c++ std functions can now be used on it. It also provides useful member functions like at which is a safe member access function with bound checking, and size which allows you to return the size of the array without calculation.

Section 24.8: Using Output Iterator

Several values of the same type can be returned by passing an output iterator to the function. This is particularly common for generic functions (like the algorithms of the standard library).

Example:

template<typename Incrementable, typename OutputIterator>

void generate_sequence(Incrementable from, Incrementable to, OutputIterator output) { for (Incrementable k = from; k != to; ++k)

*output++ = k;

GoalKicker.com – C++ Notes for Professionals

127

}

Example usage:

std::vector<int> digits;

generate_sequence(0, 10, std::back_inserter(digits)); // digits now contains {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

Section 24.9: Using std::vector

A std::vector can be useful for returning a dynamic number of variables of the same type. The following example uses int as data type, but a std::vector can hold any type that is trivially copyable:

#include <vector> #include <iostream>

//the following function returns all integers between and including 'a' and 'b' in a vector

//(the function can return up to std::vector::max_size elements with the vector, given that

//the system's main memory can hold that many items)

std::vector<int> fillVectorFrom(int a, int b) { std::vector<int> temp;

for (int i = a; i <= b; i++) { temp.push_back(i);

}

return temp;

}

int main() {

//assigns the filled vector created inside the function to the new vector 'v' std::vector<int> v = fillVectorFrom(1, 10);

//prints "1 2 3 4 5 6 7 8 9 10 "

for (int i = 0; i < v.size(); i++) { std::cout << v[i] << " ";

}

std::cout << std::endl; return 0;

}

GoalKicker.com – C++ Notes for Professionals

128