Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: be398e9d1251
Choose a base ref
...
head repository: mockingbirdnest/Principia
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: 93240d5fa243
Choose a head ref
  • 5 commits
  • 5 files changed
  • 2 contributors

Commits on Mar 26, 2017

  1. Copy the full SHA
    1e3771b View commit details
  2. lint

    eggrobin committed Mar 26, 2017
    Copy the full SHA
    a8fd2c8 View commit details
  3. space

    eggrobin committed Mar 26, 2017
    Copy the full SHA
    ac8aa2c View commit details
  4. after pleroy's review

    eggrobin committed Mar 26, 2017
    Copy the full SHA
    58e73fc View commit details
  5. Merge pull request #1291 from eggrobin/movable-function

    I am going to build my own function with move semantics and polymorphism
    pleroy authored Mar 26, 2017
    Copy the full SHA
    93240d5 View commit details
Showing with 134 additions and 0 deletions.
  1. +3 −0 base/base.vcxproj
  2. +9 −0 base/base.vcxproj.filters
  3. +50 −0 base/function.hpp
  4. +33 −0 base/function_body.hpp
  5. +39 −0 base/function_test.cpp
3 changes: 3 additions & 0 deletions base/base.vcxproj
Original file line number Diff line number Diff line change
@@ -269,6 +269,8 @@
<ClInclude Include="disjoint_sets.hpp" />
<ClInclude Include="disjoint_sets_body.hpp" />
<ClInclude Include="fingerprint2011.hpp" />
<ClInclude Include="function.hpp" />
<ClInclude Include="function_body.hpp" />
<ClInclude Include="get_line.hpp" />
<ClInclude Include="get_line_body.hpp" />
<ClInclude Include="hexadecimal.hpp" />
@@ -299,6 +301,7 @@
<ClCompile Include="bundle.cpp" />
<ClCompile Include="bundle_test.cpp" />
<ClCompile Include="disjoint_sets_test.cpp" />
<ClCompile Include="function_test.cpp" />
<ClCompile Include="hexadecimal_test.cpp" />
<ClCompile Include="not_null_test.cpp" />
<ClCompile Include="pull_serializer_test.cpp" />
9 changes: 9 additions & 0 deletions base/base.vcxproj.filters
Original file line number Diff line number Diff line change
@@ -113,6 +113,12 @@
<ClInclude Include="not_constructible.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="function.hpp">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="function_body.hpp">
<Filter>Source Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="not_null_test.cpp">
@@ -145,5 +151,8 @@
<ClCompile Include="bundle_test.cpp">
<Filter>Test Files</Filter>
</ClCompile>
<ClCompile Include="function_test.cpp">
<Filter>Test Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
50 changes: 50 additions & 0 deletions base/function.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
#pragma once

#include <memory>

namespace principia {
namespace base {
namespace internal_function {

template<typename Result, typename... Args>
class Functor {
public:
virtual ~Functor() = default;
virtual Result Call(Args&&...) = 0;
};

template<typename F, typename Result, typename... Args>
class ConcreteFunctor final : public Functor<Result, Args...> {
public:
explicit ConcreteFunctor(F functor);
Result Call(Args&&... args) final;
private:
F functor_;
};

template<typename Signature>
class function;

template<typename Result, typename... Args>
class function<Result(Args...)> {
public:
template<typename F>
function(F functor);

function(function&&) = default; // NOLINT(whitespace/operators)
function& operator=(function&&) = default;

Result operator()(Args&&... args);

private:
std::unique_ptr<Functor<Result, Args...>> functor_;
};

} // namespace internal_function

using internal_function::function;

} // namespace base
} // namespace principia

#include "base/function_body.hpp"
33 changes: 33 additions & 0 deletions base/function_body.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
#pragma once

#include <utility>

#include "base/function.hpp"

namespace principia {
namespace base {
namespace internal_function {

template<typename F, typename Result, typename... Args>
ConcreteFunctor<F, Result, Args...>::ConcreteFunctor(F functor)
: functor_(std::move(functor)) {}

template<typename F, typename Result, typename... Args>
Result ConcreteFunctor<F, Result, Args...>::Call(Args&&... args) {
return functor_(std::forward<Args>(args)...);
}

template<typename Result, typename... Args>
template<typename F>
function<Result(Args...)>::function(F functor)
: functor_(std::make_unique<ConcreteFunctor<F, Result, Args...>>(
std::move(functor))) {}

template<typename Result, typename... Args>
Result function<Result(Args...)>::operator()(Args&&... args) {
return functor_->Call(std::forward<Args>(args)...);
}

} // namespace internal_function
} // namespace base
} // namespace principia
39 changes: 39 additions & 0 deletions base/function_test.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@

#include "base/function.hpp"

#include <memory>

#include "gmock/gmock.h"
#include "gtest/gtest.h"

using ::testing::Eq;

namespace principia {
namespace base {

class FunctionTest : public testing::Test {};

TEST_F(FunctionTest, MovableFunction) {
int observe_i = 0;
function<void()> λ = [i = std::make_unique<int>(), &observe_i](){
++*i;
observe_i = *i;
};
function<void()> f = std::move(λ);
f();
EXPECT_THAT(observe_i, Eq(1));
f();
EXPECT_THAT(observe_i, Eq(2));

function<std::unique_ptr<int>(std::unique_ptr<int>)> μ =
[i = std::make_unique<int>()](std::unique_ptr<int> p) {
++*i;
*p += *i;
return std::move(p);
};
EXPECT_THAT(*μ(std::make_unique<int>(3)), Eq(4));
EXPECT_THAT(*μ(std::make_unique<int>(0)), Eq(2));
}

} // namespace base
} // namespace principia