Commit 5e2f2cd5 by Ville Voutilainen Committed by Ville Voutilainen

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
parent 41d9f1e0
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)) { }
......
#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 = "";
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment