问题
We can use std::min
in below way:
// 1.
int a = 1, b = 2;
std::min(a, b);
// 2.
std::min({1,2,3,4});
But why can't use a std::vector
or std::list
, Because the param in the template is initializer_list
.
template <class T, class Compare>
pair<T,T> minmax (initializer_list<T> il, Compare comp);
What is the reason for this design?
回答1:
To explain "why it doesn't accept a container", take the semantic into consideration:
std::min({ "foo", "bar", "hello" })
The semantic of std::min()
means "find the minimum value in the input parameters". Thus std::min()
/std::max()
takes two arguments, or an initializer_list as "more arguments".
std::min()
doesn't provide the ability to "iterate through a container", because a container is considered as "a parameter".
To find the min value in a container, there is std::min_element()
, and eerorika's suggestion std::ranges::min()
in C++20 should be better.
For std::min_element()
usage, you may refer to How can I get the max (or min) value in a vector?.
回答2:
"The more they overthink the plumbing, the easier it is to stop up the drain." – Commander Montgomery Scott
The purpose of std::min
is to return the smaller of its parameters. Simple and succinct. As with your own designs, it is better for a function (or function template) to do one thing well than to do many things poorly. Thus, std::min
has no knowledge of containers. It simply knows how to take two things and compare them. Knowledge of containers was instead granted to std::min_element
. Between the two templates, most use cases were covered.
One case that was not covered was finding the minimum of more than two elements when those elements were not the elements of a (range within a) container. This case could be handled by daisy-chaining std::min
, but it is somewhat awkward to do so. For C++11, it was decided that the benefits of handling more parameters outweighed the cost of complicating the template, as long as the complications were kept to a minimum. Thus a single, simple mechanism for supplying an arbitrary number of arguments was chosen, namely std::initializer_list
. There is no need to allow arbitrary containers because std::min_element
already covers that situation.
回答3:
But why can't use a std::vector or std::list, Because the param in the template is initializer_list.
Because there is no overload that would accept a vector or a list. Those are not initialiser lists.
Since C++20 you can use std::ranges::min
into which you can pass either of those containers or indeed any range. Prior to that, there is std::min_element
which works with any pair of iterators.
来源:https://stackoverflow.com/questions/64056886/why-does-stdmin-only-support-initializer-list