Skip to content

Commit

Permalink
Merge branch 'value-init' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
pfultz2 committed Jun 25, 2016
2 parents bbdd63b + f9cd490 commit da9ad91
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 5 deletions.
2 changes: 1 addition & 1 deletion .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ script:

- |
for build_type in debug minsizerel release; do
for asan_type in ASANVARIANT; do
for asan_type in $ASANVARIANT; do
build_dir="build-$build_type-asan-$asan_type"
mkdir $build_dir
cd $build_dir
Expand Down
75 changes: 71 additions & 4 deletions include/fit/construct.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,8 +85,75 @@ struct by_adaptor;

namespace detail {

template<class T>
template<class T, class=void>
struct construct_f
{
typedef typename std::aligned_storage<sizeof(T)>::type storage;

struct storage_holder
{
storage * s;
storage_holder(storage* x) : s(x)
{}

T& data()
{
return *reinterpret_cast<T*>(s);
}

~storage_holder()
{
this->data().~T();
}
};

constexpr construct_f()
{}
template<class... Ts, FIT_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
T operator()(Ts&&... xs) const
{
storage buffer{};
new(&buffer) T(FIT_FORWARD(Ts)(xs)...);
storage_holder h(&buffer);
return h.data();
}

template<class X, FIT_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&&)>
T operator()(std::initializer_list<X>&& x) const
{
storage buffer{};
new(&buffer) T(static_cast<std::initializer_list<X>&&>(x));
storage_holder h(&buffer);
return h.data();
}

template<class X, FIT_ENABLE_IF_CONSTRUCTIBLE(T, std::initializer_list<X>&)>
T operator()(std::initializer_list<X>& x) const
{
storage buffer{};
new(&buffer) T(x);
storage_holder h(&buffer);
return h.data();
}

template<class X, FIT_ENABLE_IF_CONSTRUCTIBLE(T, const std::initializer_list<X>&)>
T operator()(const std::initializer_list<X>& x) const
{
storage buffer{};
new(&buffer) T(x);
storage_holder h(&buffer);
return h.data();
}

template<class F>
constexpr by_adaptor<F, construct_f> by(F f) const
{
return by_adaptor<F, construct_f>(static_cast<F&&>(f), *this);
}
};

template<class T>
struct construct_f<T, typename std::enable_if<FIT_IS_LITERAL(T)>::type>
{
constexpr construct_f()
{}
Expand Down Expand Up @@ -130,7 +197,7 @@ struct construct_template_f
FIT_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
constexpr Result operator()(Ts&&... xs) const
{
return Result(FIT_FORWARD(Ts)(xs)...);
return construct_f<Result>()(FIT_FORWARD(Ts)(xs)...);
}

template<class F>
Expand All @@ -157,7 +224,7 @@ struct construct_meta_f
FIT_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
constexpr Result operator()(Ts&&... xs) const
{
return Result(FIT_FORWARD(Ts)(xs)...);
return construct_f<Result>()(FIT_FORWARD(Ts)(xs)...);
}

template<class F>
Expand All @@ -178,7 +245,7 @@ struct construct_meta_template_f
FIT_ENABLE_IF_CONSTRUCTIBLE(Result, Ts...)>
constexpr Result operator()(Ts&&... xs) const
{
return Result(FIT_FORWARD(Ts)(xs)...);
return construct_f<Result>()(FIT_FORWARD(Ts)(xs)...);
}

template<class F>
Expand Down
57 changes: 57 additions & 0 deletions test/construct.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,13 +32,70 @@ struct tuple_meta_class
};
};

struct implicit_default
{
int mem1;
std::string mem2;
};

struct user_default
{
int mem1;
std::string mem2;
user_default() { }
};

struct user_construct
{
int mem1;
std::string mem2;
user_construct(int) { }
};

template<class T>
struct template_user_construct
{
int mem1;
std::string mem2;
template_user_construct(T) { }
};


FIT_TEST_CASE()
{
auto v = fit::construct<std::vector<int>>()(5, 5);
FIT_TEST_CHECK(v.size() == 5);
FIT_TEST_CHECK(v == std::vector<int>{5, 5, 5, 5, 5});
}

FIT_TEST_CASE()
{
auto x = fit::construct<implicit_default>()();
FIT_TEST_CHECK(x.mem1 == 0);
FIT_TEST_CHECK(x.mem2 == "");
}

FIT_TEST_CASE()
{
auto x = fit::construct<user_default>()();
FIT_TEST_CHECK(x.mem1 == 0);
FIT_TEST_CHECK(x.mem2 == "");
}

FIT_TEST_CASE()
{
auto x = fit::construct<user_construct>()(3);
FIT_TEST_CHECK(x.mem1 == 0);
FIT_TEST_CHECK(x.mem2 == "");
}

FIT_TEST_CASE()
{
auto x = fit::construct<template_user_construct>()(3);
FIT_TEST_CHECK(x.mem1 == 0);
FIT_TEST_CHECK(x.mem2 == "");
}

FIT_TEST_CASE()
{
auto make = fit::construct<std::vector<int>>().by(fit::_1 * fit::_1);
Expand Down

0 comments on commit da9ad91

Please sign in to comment.