Avoid creating dangling references in case of nested tuples
for tuple constructors that construct from other tuples. 2015-09-25 Ville Voutilainen <ville.voutilainen@gmail.com> Avoid creating dangling references in case of nested tuples for tuple constructors that construct from other tuples. * include/std/tuple (_TC::_NonNestedTuple): New. * include/std/tuple (tuple::_TNTC): New. * include/std/tuple (tuple(const tuple<_UElements...>&), tuple(tuple<_UElements...>&&): Use _TNTC. * testsuite/20_util/tuple/cons/nested_tuple_construct.cc: New. From-SVN: r228134
This commit is contained in:
parent
41d9f1e039
commit
5e2f2cd584
3 changed files with 106 additions and 8 deletions
|
@ -1,3 +1,13 @@
|
|||
2015-09-25 Ville Voutilainen <ville.voutilainen@gmail.com>
|
||||
|
||||
Avoid creating dangling references in case of nested tuples
|
||||
for tuple constructors that construct from other tuples.
|
||||
* include/std/tuple (_TC::_NonNestedTuple): New.
|
||||
* include/std/tuple (tuple::_TNTC): New.
|
||||
* include/std/tuple (tuple(const tuple<_UElements...>&),
|
||||
tuple(tuple<_UElements...>&&): Use _TNTC.
|
||||
* testsuite/20_util/tuple/cons/nested_tuple_construct.cc: New.
|
||||
|
||||
2015-09-24 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/67707
|
||||
|
|
|
@ -486,6 +486,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{
|
||||
return __and_<is_convertible<_UElements&&, _Elements>...>::value;
|
||||
}
|
||||
|
||||
template<typename _SrcTuple>
|
||||
static constexpr bool _NonNestedTuple()
|
||||
{
|
||||
return __and_<__not_<is_convertible<_SrcTuple, _Elements...>>,
|
||||
__not_<is_constructible<_Elements..., _SrcTuple>>
|
||||
>::value;
|
||||
}
|
||||
};
|
||||
|
||||
template<typename... _Elements>
|
||||
|
@ -514,6 +522,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
template<typename... _UElements>
|
||||
static constexpr bool _NonNestedTuple()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
/// Primary class template, tuple
|
||||
|
@ -599,40 +613,54 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
|||
|
||||
constexpr tuple(tuple&&) = default;
|
||||
|
||||
template<typename... _UElements, typename
|
||||
// Shortcut for the cases where constructors taking tuples
|
||||
// must avoid creating temporaries.
|
||||
template<typename _Dummy> using _TNTC =
|
||||
_TC<is_same<_Dummy, void>::value && sizeof...(_Elements) == 1,
|
||||
_Elements...>;
|
||||
|
||||
template<typename... _UElements, typename _Dummy = void, typename
|
||||
enable_if<_TMC<_UElements...>::template
|
||||
_ConstructibleTuple<_UElements...>()
|
||||
&& _TMC<_UElements...>::template
|
||||
_ImplicitlyConvertibleTuple<_UElements...>(),
|
||||
_ImplicitlyConvertibleTuple<_UElements...>()
|
||||
&& _TNTC<_Dummy>::template
|
||||
_NonNestedTuple<const tuple<_UElements...>&>(),
|
||||
bool>::type=true>
|
||||
constexpr tuple(const tuple<_UElements...>& __in)
|
||||
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
|
||||
{ }
|
||||
|
||||
template<typename... _UElements, typename
|
||||
template<typename... _UElements, typename _Dummy = void, typename
|
||||
enable_if<_TMC<_UElements...>::template
|
||||
_ConstructibleTuple<_UElements...>()
|
||||
&& !_TMC<_UElements...>::template
|
||||
_ImplicitlyConvertibleTuple<_UElements...>(),
|
||||
_ImplicitlyConvertibleTuple<_UElements...>()
|
||||
&& _TNTC<_Dummy>::template
|
||||
_NonNestedTuple<const tuple<_UElements...>&>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr tuple(const tuple<_UElements...>& __in)
|
||||
: _Inherited(static_cast<const _Tuple_impl<0, _UElements...>&>(__in))
|
||||
{ }
|
||||
|
||||
template<typename... _UElements, typename
|
||||
template<typename... _UElements, typename _Dummy = void, typename
|
||||
enable_if<_TMC<_UElements...>::template
|
||||
_MoveConstructibleTuple<_UElements...>()
|
||||
&& _TMC<_UElements...>::template
|
||||
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
|
||||
_ImplicitlyMoveConvertibleTuple<_UElements...>()
|
||||
&& _TNTC<_Dummy>::template
|
||||
_NonNestedTuple<tuple<_UElements...>&&>(),
|
||||
bool>::type=true>
|
||||
constexpr tuple(tuple<_UElements...>&& __in)
|
||||
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
|
||||
|
||||
template<typename... _UElements, typename
|
||||
template<typename... _UElements, typename _Dummy = void, typename
|
||||
enable_if<_TMC<_UElements...>::template
|
||||
_MoveConstructibleTuple<_UElements...>()
|
||||
&& !_TMC<_UElements...>::template
|
||||
_ImplicitlyMoveConvertibleTuple<_UElements...>(),
|
||||
_ImplicitlyMoveConvertibleTuple<_UElements...>()
|
||||
&& _TNTC<_Dummy>::template
|
||||
_NonNestedTuple<tuple<_UElements...>&&>(),
|
||||
bool>::type=false>
|
||||
explicit constexpr tuple(tuple<_UElements...>&& __in)
|
||||
: _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { }
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
#include <string>
|
||||
#include <tuple>
|
||||
#include <testsuite_hooks.h>
|
||||
|
||||
static std::string result;
|
||||
|
||||
struct X {
|
||||
int state; // this has to be here
|
||||
X() {
|
||||
result += "Def";
|
||||
}
|
||||
|
||||
X(X const&) {
|
||||
result += "Copy";
|
||||
}
|
||||
|
||||
X(X&&) {
|
||||
result += "Move";
|
||||
}
|
||||
|
||||
~X() {
|
||||
result += "Dtor";
|
||||
}
|
||||
};
|
||||
|
||||
void f()
|
||||
{
|
||||
X v;
|
||||
std::tuple<X> t1{v};
|
||||
std::tuple<std::tuple<X>&&> t2{std::move(t1)};
|
||||
std::tuple<std::tuple<X>> t3{std::move(t2)};
|
||||
}
|
||||
|
||||
void f2()
|
||||
{
|
||||
X v;
|
||||
std::tuple<X> t1{std::move(v)};
|
||||
std::tuple<std::tuple<X>&&> t2{std::move(t1)};
|
||||
std::tuple<std::tuple<X>> t3{std::move(t2)};
|
||||
}
|
||||
|
||||
void f3()
|
||||
{
|
||||
std::tuple<X> t1{X{}};
|
||||
std::tuple<std::tuple<X>&&> t2{std::move(t1)};
|
||||
std::tuple<std::tuple<X>> t3{std::move(t2)};
|
||||
}
|
||||
|
||||
int main()
|
||||
{
|
||||
f();
|
||||
VERIFY(result == "DefCopyMoveDtorDtorDtor");
|
||||
result = "";
|
||||
f2();
|
||||
VERIFY(result == "DefMoveMoveDtorDtorDtor");
|
||||
result = "";
|
||||
f3();
|
||||
VERIFY(result == "DefMoveDtorMoveDtorDtor");
|
||||
result = "";
|
||||
}
|
Loading…
Add table
Reference in a new issue