Difference between revisions of "cpp/iterator/projected"
(+) |
m (fmt.) |
||
(11 intermediate revisions by 4 users not shown) | |||
Line 2: | Line 2: | ||
{{cpp/iterator/navbar}} | {{cpp/iterator/navbar}} | ||
{{dcl begin}} | {{dcl begin}} | ||
− | {{dcl header | iterator}} | + | {{dcl header|iterator}} |
− | {{dcl | num=1 | | + | {{dcl rev multi|num=1 |
+ | |since1=c++20|dcl1= | ||
template< std::indirectly_readable I, | template< std::indirectly_readable I, | ||
std::indirectly_regular_unary_invocable<I> Proj > | std::indirectly_regular_unary_invocable<I> Proj > | ||
− | struct projected { | + | struct projected |
+ | { | ||
using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | ||
std::indirect_result_t<Proj&, I> operator*() const; // not defined | std::indirect_result_t<Proj&, I> operator*() const; // not defined | ||
}; | }; | ||
+ | |since2=c++26|dcl2= | ||
+ | template< std::indirectly_readable I, | ||
+ | std::indirectly_regular_unary_invocable<I> Proj > | ||
+ | using projected = /*projected-impl*/<I, Proj>::/*__type*/; // see (3) | ||
}} | }} | ||
− | {{dcl | num=2 | since=c++20 | 1= | + | {{dcl|num=2|since=c++20|until=c++26|1= |
template< std::weakly_incrementable I, class Proj > | template< std::weakly_incrementable I, class Proj > | ||
− | struct incrementable_traits<std::projected<I, Proj>> { | + | struct incrementable_traits<std::projected<I, Proj>> |
+ | { | ||
using difference_type = std::iter_difference_t<I>; | using difference_type = std::iter_difference_t<I>; | ||
+ | }; | ||
+ | }} | ||
+ | {{dcl|num=3|since=c++26|notes={{mark expos}}|1= | ||
+ | template< class I, class Proj > | ||
+ | struct /*projected-impl*/ | ||
+ | { | ||
+ | struct /*__type*/ | ||
+ | { | ||
+ | using value_type = std::remove_cvref_t<std::indirect_result_t<Proj&, I>>; | ||
+ | using difference_type = std::iter_difference_t<I>; // conditionally present | ||
+ | |||
+ | std::indirect_result_t<Proj&, I> operator*() const; // not defined | ||
+ | }; | ||
}; | }; | ||
}} | }} | ||
{{dcl end}} | {{dcl end}} | ||
− | @1@ Class template {{tt|projected}} combines an {{lconcept|indirectly_readable}} type I and a callable object type {{tt|Proj}} into a new {{tt|indirectly_readable}} type whose reference type is the result of applying {{tt|Proj}} to the {{c|std::iter_reference_t<I>}}. | + | @1@ {{rev inl|until=c++26|Class}}{{rev inl|since=c++26|Alias}} template {{tt|projected}} combines an {{lconcept|indirectly_readable}} type {{tt|I}} and a callable object type {{tt|Proj}} into a new {{tt|indirectly_readable}} type whose reference type is the result of applying {{tt|Proj}} to the {{c|std::iter_reference_t<I>}}. |
− | @2@ This specialization of {{ | + | @2@ This specialization of {{lc|std::incrementable_traits}} makes {{c|std::projected<I, Proj>}} a {{lconcept|weakly_incrementable}} type when {{tt|I}} is also a {{tt|weakly_incrementable}} type. |
− | {{tt|projected}} is | + | @3@ An indirect layer used for avoiding unexpected [[cpp/language/adl|argument-dependent lookup]]. The member type {{tt|difference_type}} exists only if {{tt|I}} models {{lconcept|weakly_incrementable}}. |
+ | |||
+ | {{tt|projected}} is used only to constrain algorithms that accept callable objects and projections, and hence its {{c|operator*()}} is not defined. | ||
===Template parameters=== | ===Template parameters=== | ||
{{par begin}} | {{par begin}} | ||
− | {{par | I | an indirectly readable type}} | + | {{par|I|an indirectly readable type}} |
− | {{par | Proj | projection applied to a dereferenced {{tt|I}} }} | + | {{par|Proj|projection applied to a dereferenced {{tt|I}}}} |
{{par end}} | {{par end}} | ||
+ | |||
+ | ===Notes=== | ||
+ | The indirect layer prevents {{tt|I}} and {{tt|Proj}} to be associated classes of {{tt|projected}}. When an associated class of {{tt|I}} or {{tt|Proj}} is an incomplete class type, the indirect layer avoids the unnecessary attempt to inspect the definition of that type that results in hard error. | ||
+ | |||
+ | ===Example=== | ||
+ | {{example | ||
+ | |code= | ||
+ | #include <algorithm> | ||
+ | #include <cassert> | ||
+ | #include <functional> | ||
+ | #include <iterator> | ||
+ | |||
+ | template<class T> | ||
+ | struct Holder | ||
+ | { | ||
+ | T t; | ||
+ | }; | ||
+ | |||
+ | struct Incomplete; | ||
+ | |||
+ | using P = Holder<Incomplete>*; | ||
+ | |||
+ | static_assert(std::equality_comparable<P>); // OK | ||
+ | static_assert(std::indirectly_comparable<P*, P*, std::equal_to<>>); // Error before C++26 | ||
+ | static_assert(std::sortable<P*>); // Error before C++26 | ||
+ | |||
+ | int main() | ||
+ | { | ||
+ | P a[10] = {}; // ten null pointers | ||
+ | assert(std::count(a, a + 10, nullptr) == 10); // OK | ||
+ | assert(std::ranges::count(a, a + 10, nullptr) == 10); // Error before C++26 | ||
+ | } | ||
+ | }} | ||
+ | |||
+ | ===See also=== | ||
+ | {{dsc begin}} | ||
+ | {{dsc inc|cpp/iterator/dsc projected_value_t}} | ||
+ | {{dsc end}} | ||
{{langlinks|es|ja|zh}} | {{langlinks|es|ja|zh}} |
Latest revision as of 14:43, 12 April 2024
Defined in header <iterator>
|
||
(1) | ||
template< std::indirectly_readable I, std::indirectly_regular_unary_invocable<I> Proj > |
(since C++20) (until C++26) |
|
template< std::indirectly_readable I, std::indirectly_regular_unary_invocable<I> Proj > |
(since C++26) | |
template< std::weakly_incrementable I, class Proj > struct incrementable_traits<std::projected<I, Proj>> |
(2) | (since C++20) (until C++26) |
template< class I, class Proj > struct /*projected-impl*/ |
(3) | (since C++26) (exposition only*) |
projected
combines an indirectly_readable
type I
and a callable object type Proj
into a new indirectly_readable
type whose reference type is the result of applying Proj
to the std::iter_reference_t<I>.weakly_incrementable
type when I
is also a weakly_incrementable
type.difference_type
exists only if I
models weakly_incrementable
.projected
is used only to constrain algorithms that accept callable objects and projections, and hence its operator*() is not defined.
Contents |
[edit] Template parameters
I | - | an indirectly readable type |
Proj | - | projection applied to a dereferenced I
|
[edit] Notes
The indirect layer prevents I
and Proj
to be associated classes of projected
. When an associated class of I
or Proj
is an incomplete class type, the indirect layer avoids the unnecessary attempt to inspect the definition of that type that results in hard error.
[edit] Example
#include <algorithm> #include <cassert> #include <functional> #include <iterator> template<class T> struct Holder { T t; }; struct Incomplete; using P = Holder<Incomplete>*; static_assert(std::equality_comparable<P>); // OK static_assert(std::indirectly_comparable<P*, P*, std::equal_to<>>); // Error before C++26 static_assert(std::sortable<P*>); // Error before C++26 int main() { P a[10] = {}; // ten null pointers assert(std::count(a, a + 10, nullptr) == 10); // OK assert(std::ranges::count(a, a + 10, nullptr) == 10); // Error before C++26 }
[edit] See also
(C++26) |
computes the value type of an indirectly_readable type by projection(alias template) |