// { dg-options "-std=gnu++0x" }
// Copyright (C) 2012-2014 Free Software Foundation, Inc.
//
// This file is part of the GNU ISO C++ Library. This library is free
// software; you can redistribute it and/or modify it under the
// terms of the GNU General Public License as published by the
// Free Software Foundation; either version 3, or (at your option)
// any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License along
// with this library; see the file COPYING3. If not see
// .
#include
#include
#include
#include
#include
// 20.12.4 Scoped allocator adaptor members [allocator.adaptor.members]
//
// Test piecewise construction of std::pair by scoped_allocator_adaptor
using __gnu_test::uneq_allocator;
using std::scoped_allocator_adaptor;
// a DefaultConstructible and CopyConstructible type
struct def
{
def() : id(999) { }
int id;
};
// a CopyConstructible and non-DefaultConstructible type
struct copyable
{
copyable(int id) : id(id) { }
// not constructed with an allocator so nothing to test
bool verify() const { return true; }
int id;
};
// a MoveConstructible and non-DefaultConstructible type
struct move_only
{
move_only(int id) : id(id) { }
move_only(move_only&&) = default;
// not constructed with an allocator so nothing to test
bool verify() const { return true; }
int id;
};
// a type for which std::uses_allocator is true
struct uses_alloc_post
{
typedef uneq_allocator allocator_type;
uses_alloc_post(const allocator_type& alloc)
: allocator_personality(alloc.get_personality()), id(999)
{ }
uses_alloc_post(copyable arg, const allocator_type& alloc)
: allocator_personality(alloc.get_personality()), id(arg.id)
{ }
uses_alloc_post(move_only arg, const allocator_type& alloc)
: allocator_personality(alloc.get_personality()), id(arg.id)
{ }
// allocator-extended copy ctor
uses_alloc_post(const uses_alloc_post& other, const allocator_type& alloc)
: allocator_personality(alloc.get_personality()), id(other.id)
{ }
// verify we were constructed with right allocator
bool verify() const { return allocator_personality == id; }
int allocator_personality;
int id;
};
// a type for which std::uses_allocator is true
struct uses_alloc_pre : uses_alloc_post
{
typedef uneq_allocator allocator_type;
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc)
: uses_alloc_post(alloc)
{ }
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc,
copyable arg)
: uses_alloc_post(arg, alloc)
{ }
// allocator-extended copy ctor
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc,
const uses_alloc_pre& other)
: uses_alloc_post(other, alloc)
{ }
uses_alloc_pre(std::allocator_arg_t, const allocator_type& alloc,
move_only arg)
: uses_alloc_post(std::move(arg), alloc)
{ }
};
template
void
test_def()
{
bool test __attribute((unused)) = false;
typedef std::pair test_type;
typedef uneq_allocator alloc_type;
typedef scoped_allocator_adaptor alloc_adaptor;
int inner_id = 2;
alloc_adaptor a(-1, alloc_type(inner_id)); // outer=-1, inner=2
// all pair members that can be constructed with an allocator
// should be constructed with the inner allocator, with personality==2
auto p = a.allocate(1);
// construct(pair* p, piecewise_construct_t, tuple<...>, tuple<...>)
std::tuple<> t;
a.construct(p, std::piecewise_construct, t, t);
VERIFY( p->first.id == 999 );
VERIFY( p->second.id == 999 );
a.destroy(p);
// construct(pair* __p)
a.construct(p);
VERIFY( p->first.id == 999 );
VERIFY( p->second.id == 999 );
auto pp = *p;
a.destroy(p);
// construct(pair* p, const pair& x)
a.construct(p, pp);
VERIFY( p->first.id == 999 );
VERIFY( p->second.id == 999 );
a.destroy(p);
// construct(pair* p, pair&& x)
a.construct(p, std::move(pp));
VERIFY( p->first.id == 999 );
VERIFY( p->second.id == 999 );
a.destroy(p);
a.deallocate(p, 1);
}
template
void
test_copying()
{
bool test __attribute((unused)) = false;
typedef std::pair test_type;
typedef uneq_allocator alloc_type;
typedef scoped_allocator_adaptor alloc_adaptor;
int inner_id = 2;
alloc_adaptor a(-1, alloc_type(inner_id)); // outer=-1, inner=2
// all pair members that can be constructed with an allocator
// should be constructed with the inner allocator, with personality==2
auto p = a.allocate(1);
// construct(pair* p, piecewise_construct_t, tuple<...>, tuple<...>)
auto t = std::make_tuple(copyable(inner_id));
a.construct(p, std::piecewise_construct, t, t);
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
a.destroy(p);
// construct(pair* __p)
// cannot test this overload using non-DefaultConstructible types
// construct(pair* p, U&& x, V&& y)
copyable c(inner_id);
a.construct(p, c, c);
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
auto pp = *p;
a.destroy(p);
// construct(pair* p, const pair& x)
a.construct(p, pp);
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
a.destroy(p);
// construct(pair* p, pair&& x)
a.construct(p, std::move(pp));
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
a.destroy(p);
a.deallocate(p, 1);
}
template
void
test_moving()
{
bool test __attribute((unused)) = false;
typedef std::pair test_type;
typedef uneq_allocator alloc_type;
typedef scoped_allocator_adaptor alloc_adaptor;
int inner_id = 2;
alloc_adaptor a(-1, alloc_type(inner_id)); // outer=-1, inner=2
// all pair members that can be constructed with an allocator
// should be constructed with the inner allocator, with personality==2
auto p = a.allocate(1);
// construct(pair* p, piecewise_construct_t, tuple<...>, tuple<...>)
a.construct(p, std::piecewise_construct,
std::make_tuple(move_only(inner_id)),
std::make_tuple(move_only(inner_id)));
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
a.destroy(p);
// construct(pair* __p)
// cannot test this overload using non-DefaultConstructible types
// construct(pair* p, U&& x, V&& y)
a.construct(p, move_only(inner_id), move_only(inner_id));
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
a.destroy(p);
// construct(pair* p, const pair& x)
// cannot test this overload using move-only types
// construct(pair* p, pair&& x)
a.construct(p, std::make_pair(move_only(inner_id), move_only(inner_id)));
VERIFY( p->first.verify() );
VERIFY( p->second.verify() );
a.destroy(p);
a.deallocate(p, 1);
}
void test01()
{
test_def();
test_def();
test_def();
test_def();
test_def();
test_def();
test_def();
test_def();
test_def();
}
void test02()
{
test_copying();
test_copying();
test_copying();
test_copying();
test_copying();
test_copying();
test_copying();
test_copying();
test_copying();
}
void test03()
{
test_moving();
test_moving();
test_moving();
test_moving();
test_moving();
test_moving();
test_moving();
test_moving();
test_moving();
}
int main()
{
test01();
test02();
test03();
}