Fix std::function allocator constructors in C++03.

The C++03 version of function tried to default construct the allocator
in the uses allocator constructors when no allocation was performed. These
constructors would fail to compile when used with allocators that had no
default constructor.


git-svn-id: https://llvm.org/svn/llvm-project/libcxx/trunk@239708 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Eric Fiselier
2015-06-14 23:30:09 +00:00
parent 4983580dc5
commit b05f0599c0
5 changed files with 239 additions and 144 deletions

View File

@@ -17,84 +17,90 @@
#include <cassert>
#include "min_allocator.h"
#include "test_allocator.h"
#include "count_new.hpp"
#include "../function_types.h"
class A
class DummyClass {};
template <class FuncType, class AllocType>
void test_FunctionObject(AllocType& alloc)
{
int data_[10];
public:
static int count;
A()
assert(globalMemCounter.checkOutstandingNewEq(0));
{
++count;
for (int i = 0; i < 10; ++i)
data_[i] = i;
FunctionObject target;
assert(FunctionObject::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(0));
std::function<FuncType> f2(std::allocator_arg, alloc, target);
assert(FunctionObject::count == 2);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f2.template target<FunctionObject>());
assert(f2.template target<FuncType>() == 0);
assert(f2.template target<FuncType*>() == 0);
}
assert(FunctionObject::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
}
A(const A&) {++count;}
~A() {--count;}
int operator()(int i) const
template <class FuncType, class AllocType>
void test_FreeFunction(AllocType& alloc)
{
assert(globalMemCounter.checkOutstandingNewEq(0));
{
for (int j = 0; j < 10; ++j)
i += data_[j];
return i;
FuncType* target = &FreeFunction;
assert(globalMemCounter.checkOutstandingNewEq(0));
std::function<FuncType> f2(std::allocator_arg, alloc, target);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.template target<FuncType*>());
assert(*f2.template target<FuncType*>() == target);
assert(f2.template target<FuncType>() == 0);
assert(f2.template target<DummyClass>() == 0);
}
assert(globalMemCounter.checkOutstandingNewEq(0));
}
int foo(int) const {return 1;}
};
template <class TargetType, class FuncType, class AllocType>
void test_MemFunClass(AllocType& alloc)
{
assert(globalMemCounter.checkOutstandingNewEq(0));
{
TargetType target = &MemFunClass::foo;
assert(globalMemCounter.checkOutstandingNewEq(0));
std::function<FuncType> f2(std::allocator_arg, alloc, target);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.template target<TargetType>());
assert(*f2.template target<TargetType>() == target);
assert(f2.template target<FuncType*>() == 0);
}
assert(globalMemCounter.checkOutstandingNewEq(0));
}
int A::count = 0;
template <class Alloc>
void test_for_alloc(Alloc& alloc) {
test_FunctionObject<int()>(alloc);
test_FunctionObject<int(int)>(alloc);
test_FunctionObject<int(int, int)>(alloc);
test_FunctionObject<int(int, int, int)>(alloc);
int g(int) {return 0;}
test_FreeFunction<int()>(alloc);
test_FreeFunction<int(int)>(alloc);
test_FreeFunction<int(int, int)>(alloc);
test_FreeFunction<int(int, int, int)>(alloc);
class Foo {
public:
void bar(int k) { }
};
test_MemFunClass<int(MemFunClass::*)() const, int(MemFunClass&)>(alloc);
test_MemFunClass<int(MemFunClass::*)(int) const, int(MemFunClass&, int)>(alloc);
test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc);
}
int main()
{
{
std::function<int(int)> f(std::allocator_arg, bare_allocator<A>(), A());
assert(A::count == 1);
assert(f.target<A>());
assert(f.target<int(*)(int)>() == 0);
}
assert(A::count == 0);
{
std::function<int(int)> f(std::allocator_arg, bare_allocator<int(*)(int)>(), g);
assert(f.target<int(*)(int)>());
assert(f.target<A>() == 0);
bare_allocator<DummyClass> bare_alloc;
test_for_alloc(bare_alloc);
}
{
std::function<int(int)> f(std::allocator_arg, bare_allocator<int(*)(int)>(),
(int (*)(int))0);
assert(!f);
assert(f.target<int(*)(int)>() == 0);
assert(f.target<A>() == 0);
}
{
std::function<int(const A*, int)> f(std::allocator_arg,
bare_allocator<int(A::*)(int)const>(),
&A::foo);
assert(f);
assert(f.target<int (A::*)(int) const>() != 0);
}
#if __cplusplus >= 201103L
{
Foo f;
std::function<void(int)> fun = std::bind(&Foo::bar, &f, std::placeholders::_1);
fun(10);
}
#endif
{
std::function<void(int)> fun(std::allocator_arg,
bare_allocator<int(*)(int)>(),
&g);
assert(fun);
assert(fun.target<int(*)(int)>() != 0);
fun(10);
non_default_test_allocator<DummyClass> non_default_alloc(42);
test_for_alloc(non_default_alloc);
}
}

View File

@@ -20,81 +20,105 @@
#include "min_allocator.h"
#include "test_allocator.h"
#include "count_new.hpp"
#include "../function_types.h"
class A
class DummyClass {};
template <class FuncType, class AllocType>
void test_FunctionObject(AllocType& alloc)
{
int data_[10];
public:
static int count;
A()
assert(globalMemCounter.checkOutstandingNewEq(0));
{
++count;
for (int i = 0; i < 10; ++i)
data_[i] = i;
// Construct function from FunctionObject.
std::function<FuncType> f = FunctionObject();
assert(FunctionObject::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f.template target<FunctionObject>());
assert(f.template target<FuncType>() == 0);
assert(f.template target<FuncType*>() == 0);
// Copy function with allocator
std::function<FuncType> f2(std::allocator_arg, alloc, f);
assert(FunctionObject::count == 2);
assert(globalMemCounter.checkOutstandingNewEq(2));
assert(f2.template target<FunctionObject>());
assert(f2.template target<FuncType>() == 0);
assert(f2.template target<FuncType*>() == 0);
}
assert(FunctionObject::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
}
A(const A&) {++count;}
~A() {--count;}
int operator()(int i) const
template <class FuncType, class AllocType>
void test_FreeFunction(AllocType& alloc)
{
assert(globalMemCounter.checkOutstandingNewEq(0));
{
for (int j = 0; j < 10; ++j)
i += data_[j];
return i;
// Construct function from function pointer.
FuncType* target = &FreeFunction;
std::function<FuncType> f = target;
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f.template target<FuncType*>());
assert(*f.template target<FuncType*>() == target);
assert(f.template target<FuncType>() == 0);
// Copy function with allocator
std::function<FuncType> f2(std::allocator_arg, alloc, f);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.template target<FuncType*>());
assert(*f2.template target<FuncType*>() == target);
assert(f2.template target<FuncType>() == 0);
}
};
assert(globalMemCounter.checkOutstandingNewEq(0));
}
int A::count = 0;
template <class TargetType, class FuncType, class AllocType>
void test_MemFunClass(AllocType& alloc)
{
assert(globalMemCounter.checkOutstandingNewEq(0));
{
// Construct function from function pointer.
TargetType target = &MemFunClass::foo;
std::function<FuncType> f = target;
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f.template target<TargetType>());
assert(*f.template target<TargetType>() == target);
assert(f.template target<FuncType*>() == 0);
// Copy function with allocator
std::function<FuncType> f2(std::allocator_arg, alloc, f);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.template target<TargetType>());
assert(*f2.template target<TargetType>() == target);
assert(f2.template target<FuncType*>() == 0);
}
assert(globalMemCounter.checkOutstandingNewEq(0));
}
int g(int) {return 0;}
template <class Alloc>
void test_for_alloc(Alloc& alloc)
{
// Large FunctionObject -- Allocation should occur
test_FunctionObject<int()>(alloc);
test_FunctionObject<int(int)>(alloc);
test_FunctionObject<int(int, int)>(alloc);
test_FunctionObject<int(int, int, int)>(alloc);
// Free function -- No allocation should occur
test_FreeFunction<int()>(alloc);
test_FreeFunction<int(int)>(alloc);
test_FreeFunction<int(int, int)>(alloc);
test_FreeFunction<int(int, int, int)>(alloc);
// Member function -- No allocation should occur.
test_MemFunClass<int(MemFunClass::*)() const, int(MemFunClass&)>(alloc);
test_MemFunClass<int(MemFunClass::*)(int) const, int(MemFunClass&, int)>(alloc);
test_MemFunClass<int(MemFunClass::*)(int, int) const, int(MemFunClass&, int, int)>(alloc);
}
int main()
{
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f = A();
assert(A::count == 1);
assert(globalMemCounter.checkOutstandingNewEq(1));
assert(f.target<A>());
assert(f.target<int(*)(int)>() == 0);
std::function<int(int)> f2(std::allocator_arg, bare_allocator<A>(), f);
assert(A::count == 2);
assert(globalMemCounter.checkOutstandingNewEq(2));
assert(f2.target<A>());
assert(f2.target<int(*)(int)>() == 0);
}
assert(A::count == 0);
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f = g;
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f.target<int(*)(int)>());
assert(f.target<A>() == 0);
std::function<int(int)> f2(std::allocator_arg, bare_allocator<int(*)(int)>(), f);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.target<int(*)(int)>());
assert(f2.target<A>() == 0);
}
assert(globalMemCounter.checkOutstandingNewEq(0));
{
assert(globalMemCounter.checkOutstandingNewEq(0));
non_default_test_allocator<std::function<int(int)> > al(1);
std::function<int(int)> f2(std::allocator_arg, al, g);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.target<int(*)(int)>());
assert(f2.target<A>() == 0);
}
assert(globalMemCounter.checkOutstandingNewEq(0));
{
std::function<int(int)> f;
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f.target<int(*)(int)>() == 0);
assert(f.target<A>() == 0);
std::function<int(int)> f2(std::allocator_arg, bare_allocator<int>(), f);
assert(globalMemCounter.checkOutstandingNewEq(0));
assert(f2.target<int(*)(int)>() == 0);
assert(f2.target<A>() == 0);
}
{
bare_allocator<DummyClass> alloc;
test_for_alloc(alloc);
}
{
non_default_test_allocator<DummyClass> alloc(42);
test_for_alloc(alloc);
}
}