Tuples Herb Sutter

zhaozj2021-02-12  176

Tuples

Herb SUTTER (Tao Ziyin Translation)

Just like the last report, in the 2002 October Standard meeting, two library expansion as a standard library, and passed.

1 is Object Wrappers of Doug Gregor's proposed polymorphism.

2 Jaakko Järvi's tuple type.

Both of these are directly in the BOOST project. (Boost Project is a C Libraries collection) last time, I promised to introduce these two extension libraries in this period, this month, let me briefly introduce the TUPLE type.

Tuple Types: A simple Motivating example

If you want to return more than one return value with a function, for example:

// Yields a quotient only

//

INTEGERDIVIDE (INT N, INT D) {

Return n / d;

}

// Sample Use:

Cout << "quotient =" << integerdivide (5, 4);

Is there any mistake in this implementation? Maybe not, after all, in the compiler, we embed integer division. The result can also be rounded out from the results.

But if we want to do more. In particular, it is necessary to provide a method to obtain other information, such as the remainder of the division. If there is no change in the function. Then, the function of achieving such a requirement is not an easy task.

One way we add an output variable in the function.

// EXAMPLE 1 (b): Integer Division,

// Yielding a quotient and remainder,

// one as the return value and one VIA

// An Output Parameter

//

INTEGERDIVIDE (INT N, INT D, INT & R) {

R = N% D;

Return n / d;

}

// Sample Use:

Int remainder;

INT quotient = integerIvide (5, 4, remainder);

Cout << "quotient =" << quotient

<< "remainder =" << remainder;

The implementation of this method is compared, but we often do this. This way is a bit incredible by returning a function return value by returning value and output variables. Some people may say that the following methods are better.

// Example 1 (c): Integer Division,

// Yielding a quotient and remainder,

// this Time Via Two Output Parameters

//

Void Integerdivide (int N, int D, int & ration INT & R) {

R = N% D;

Q = N / D;

}

// Sample Use:

Int quotient, remainder;

Integerdivide (5, 4, quotient, remainder);

Cout << "quotient =" << quotient

<< "remainder =" << remainder;

This approach may be more coordinated. But it is still relatively vague, not satisfactory. I want to think about it, we will remember why: Ralph Waldo Emerson suggests us: "A foolish consistency is the hobgoblin of limited minds." This version can work normally, but if you think it is unstable, I will not blame you. So what should I do? At this point, we usually think of we have a tool in the standard library: std :: pair, after all, there are many functions in the standard template library, which can return a few values, the Iterator scope is as a separate value - at the same time, most of them pass pair Implemented, the same method can run, as follows:

// Example 1 (d): Integer Division,

// Yielding a quotient and remainder,

// this time Both in The Return Value

//

Std :: Pair integerdivide (int N, int d) {

Return Pair (n / d, n% d);

}

// Sample Use:

PAIR quot_rem = integerIvide (5, 4);

Cout << "quotient =" << quot_rem.first

<< "remainder =" << quot_rem.second;

It can be seen that this is a satisfactory approach, and it can also improve it.

Tuples in action

Some languages, including Haskell, ML, and Python, all support Tuple Types. C is not the case, because C is a system language that can do anything, and built-in standard libraries, so we can, implement our own Tuple Types in the form of a library. Language like Java is to pack Tuple Type as a series of PAIRs. Tuple

Type and "Bundle-O-VALUES" are very similar.

In the following tuple-zeed IntegerDivide example, it is very similar, but we don't have to be confused, after all, it is using a new way:

// EXAMPLE 2 (a): Integer Division,

// Yielding a quotient and remainder,

// via a type return Type

//

Tuple integerdivide (int N, int d) {

Return Tuple (n / d, n% d);

}

// Sample Use:

TUPLE quot_rem = integerIvide (5, 4);

COUT << "quotient =" << quot_rem.get <0> ()

<< "remainder =" << quot_rem.get <1> ();

The syntax of this example is not pair so elegant, but it is as simple as PAIRS. On the other hand, Typle is not limited to only two members, which can have any more members, so it can bundle any multiple values, let's see the example below:

// Example 2 (b): floating-point division,

// Yielding a quotient and remainder,

// But also an underflow

//

Tuple // quotient, remainder, underflow

FLOATDIVIDE (FLOAT N, FLOAT D) {

//

}

If we use std :: pair to implement, then this will be like this, std :: pair >>, (Translation: This may see the advantage of Tuple )

However, we can't always use Tuple as Bundle-O-Values. There are some ways to put some independent variables into tuple. This is useful for bundling values ​​and solitary values. For example, we returned to the first example.

// EXAMPLE 3: Bundling and UNBundling

// Using "TIE"

//

Tuple integerdivide (int N, int d) {

Return Tuple (n / d, n% d);

}

// Sample Use:

Int quotient, remainder;

Tie (Quotient, Remainder) = IntegerDivide (5, 4);

Cout << "quotient =" << quotient

<< "remainder =" << remainder;

With this method, we don't have to write the output variables we don't like to write, tuples has its own input, output symbol, and demographic operation symbol.

// EXAMPLE 4 (a): streaming tuples

//

TUPLE quot_rem = integerIvide (5, 4);

COUT << quot_rem; // "(1 1)"

On the other hand, if you want to play your talents, you can control parentheses and dividends.

// EXAMPLE 4 (B): Customizing Streamed Tuples

//

TUPLE quot_rem = integerIvide (5, 4);

Cout << tuples :: set_open ('['] << Tuples :: set_close (')')

<< tuples :: set_delimiter (',')

<< quot_rem; // "[1,1]"

If you are interested, you can refer to the implementation of tuple in Boost, (www.boost.org),

Next foreland:

In the next period, I will explain in detail the function mechanism.

转载请注明原文地址:https://www.9cbs.com/read-6223.html

New Post(0)