stl2
stl2 copied to clipboard
`std::tie` is currently incompatible with foo_result
From cmcstl2's partial_sort_copy:
std::tie(first, r) = ext::copy(std::move(first), last, std::move(r), result_last);
Diagnostic:
cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp: In instantiation of ‘constexpr I2 __stl2::__partial_sort_copy_fn::operator()(I1, S1, I2, S2, Comp, Proj1, Proj2) const [with I1 = int*; S1 = int*; I2 = int*; S2 = int*; Comp = __stl2::less<void>; Proj1 = __stl2::identity; Proj2 = __stl2::identity]’:
cmcstl2/test/algorithm/partial_sort_copy.cpp:119:38: required from here
cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:43:25: error: no match for ‘operator=’ (operand types are ‘std::tuple<int*&, int*&>’ and ‘__stl2::copy_result<int*, int*>’)
std::tie(first, r) =
~~~~~~~~~~~~~~~~~~~^
ext::copy(std::move(first), last, std::move(r), result_last);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/functional:54,
from cmcstl2/include/stl2/functional.hpp:16,
from cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:16,
from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
/usr/include/c++/8/tuple:1209:7: note: candidate: ‘std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(const std::tuple<_T1, _T2>&) [with _T1 = int*&; _T2 = int*&]’
operator=(const tuple& __in)
^~~~~~~~
/usr/include/c++/8/tuple:1209:7: note: no known conversion for argument 1 from ‘__stl2::copy_result<int*, int*>’ to ‘const std::tuple<int*&, int*&>&’
/usr/include/c++/8/tuple:1216:7: note: candidate: ‘std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(std::tuple<_T1, _T2>&&) [with _T1 = int*&; _T2 = int*&]’
operator=(tuple&& __in)
^~~~~~~~
/usr/include/c++/8/tuple:1216:7: note: no known conversion for argument 1 from ‘__stl2::copy_result<int*, int*>’ to ‘std::tuple<int*&, int*&>&&’
/usr/include/c++/8/tuple:1225:9: note: candidate: ‘template<class _U1, class _U2> std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(const std::tuple<_U1, _U2>&) [with _U1 = _U1; _U2 = _U2; _T1 = int*&; _T2 = int*&]’
operator=(const tuple<_U1, _U2>& __in)
^~~~~~~~
/usr/include/c++/8/tuple:1225:9: note: template argument deduction/substitution failed:
In file included from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:43:25: note: ‘__stl2::copy_result<int*, int*>’ is not derived from ‘const std::tuple<_T1, _T2>’
std::tie(first, r) =
~~~~~~~~~~~~~~~~~~~^
ext::copy(std::move(first), last, std::move(r), result_last);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/functional:54,
from cmcstl2/include/stl2/functional.hpp:16,
from cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:16,
from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
/usr/include/c++/8/tuple:1233:9: note: candidate: ‘template<class _U1, class _U2> std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(std::tuple<_U1, _U2>&&) [with _U1 = _U1; _U2 = _U2; _T1 = int*&; _T2 = int*&]’
operator=(tuple<_U1, _U2>&& __in)
^~~~~~~~
/usr/include/c++/8/tuple:1233:9: note: template argument deduction/substitution failed:
In file included from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:43:25: note: ‘__stl2::copy_result<int*, int*>’ is not derived from ‘std::tuple<_T1, _T2>’
std::tie(first, r) =
~~~~~~~~~~~~~~~~~~~^
ext::copy(std::move(first), last, std::move(r), result_last);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/functional:54,
from cmcstl2/include/stl2/functional.hpp:16,
from cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:16,
from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
/usr/include/c++/8/tuple:1241:9: note: candidate: ‘template<class _U1, class _U2> std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(const std::pair<_U1, _U2>&) [with _U1 = _U1; _U2 = _U2; _T1 = int*&; _T2 = int*&]’
operator=(const pair<_U1, _U2>& __in)
^~~~~~~~
/usr/include/c++/8/tuple:1241:9: note: template argument deduction/substitution failed:
In file included from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:43:25: note: ‘__stl2::copy_result<int*, int*>’ is not derived from ‘const std::pair<_T1, _T2>’
std::tie(first, r) =
~~~~~~~~~~~~~~~~~~~^
ext::copy(std::move(first), last, std::move(r), result_last);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/8/functional:54,
from cmcstl2/include/stl2/functional.hpp:16,
from cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:16,
from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
/usr/include/c++/8/tuple:1250:9: note: candidate: ‘template<class _U1, class _U2> std::tuple<_T1, _T2>& std::tuple<_T1, _T2>::operator=(std::pair<_U1, _U2>&&) [with _U1 = _U1; _U2 = _U2; _T1 = int*&; _T2 = int*&]’
operator=(pair<_U1, _U2>&& __in)
^~~~~~~~
/usr/include/c++/8/tuple:1250:9: note: template argument deduction/substitution failed:
In file included from cmcstl2/test/algorithm/partial_sort_copy.cpp:21:
cmcstl2/include/stl2/detail/algorithm/partial_sort_copy.hpp:43:25: note: ‘__stl2::copy_result<int*, int*>’ is not derived from ‘std::pair<_T1, _T2>’
std::tie(first, r) =
~~~~~~~~~~~~~~~~~~~^
ext::copy(std::move(first), last, std::move(r), result_last);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
A viable solution will possibly need to go through LEWG first, but I am of the opinion that this is a workaround, not the way things should be done:
{
auto result = ext::copy(std::move(first), last, std::move(r), result_last);
first = std::move(result.in);
r = std::move(result.out);
}
Proposal 1
Make copy_result<I, O>
, etc. implicitly convertible to tuple<I&, O&>
for non-const
rvalues only.
I don't expect people to start misusing this particular feature, but I could be naïve.
Proposal 2
Add exposition-only result types that all result types can inherit from, (e.g. struct copy_result : __in_out_result<I, O>
), and add a constructor to std::tuple
for each exposition-only result type:
template<class X>
requires Same<remove_reference_t<X>, __in_out_result<I, O>> // deliberately not remove_cvref_t
tuple(X&& algorithm_result);
I am not sure of the implications for this one.
Proposal 3
Change std::tie
so that it returns an object of an exposition-only type that's common to all result types, std::tuple
, and std::pair
, and provide constructors for this common type.
Again, I'm not sure of the implications, and it's potentially a lot of extra work involved. Having said that, it does feel like the best of the three solutions I've thought of so far, since we can have other yet-to-be-invented types take advantage of std::tie
.
It's a language issue that we don't have an SB-equivalent for existing things.
I'd say that this is NAD.
I think this issue inadvertently asks for something that rhymes with __common_tuple
, so I might investigate if this is possible, and then mention it in P1035R2 if it is relevant.
That is, assuming @caseycarter doesn't convince me to nuke __common_tuple
altogether.
I would love for the need for __commom_tuple
to die. I would also like the tuple
and pair
assignment operators to accept any type that is compatible with the structured binding of the appropriate arity.
This feels more like a feature request than a proper issue to me. LEWG very deliberately chose to break anything tuple
-related when they asked for named return types. It's very much by design that "std::tie
is currently incompatible with foo_result
."
That is, assuming @CaseyCarter doesn't convince me to nuke
__common_tuple
altogether.
It would be silly to add another generic product type with reference semantics to the standard library. If tuple
isn't generic and/or reference-y enough we should fix it. We don't want to duplicate all the support machinery, we really don't want to introduce 8 more overloads of std::get
.