Skip to content

Commit

Permalink
Merge pull request #36 from leapmotion/feature-autoconstruct
Browse files Browse the repository at this point in the history
Relaxing rules on CoreContext::Construct, adding unit test
  • Loading branch information
gtremper committed Aug 7, 2014
2 parents ae2ea81 + e95ea69 commit d8e84a3
Show file tree
Hide file tree
Showing 5 changed files with 38 additions and 22 deletions.
4 changes: 3 additions & 1 deletion autowiring/CoreContext.h
Expand Up @@ -518,8 +518,10 @@ class CoreContext:

/// <summary>
/// Utility method which will inject the specified types into this context
/// Arguments will be passed to the T constructor if provided
/// </summary>
/// <remarks>
/// Arguments will be passed to the T constructor if provided
/// </remarks>
template<typename T, typename... Args>
std::shared_ptr<T> Construct(Args&&... args) {
// Add this type to the TypeRegistry
Expand Down
1 change: 0 additions & 1 deletion autowiring/CreationRules.h
Expand Up @@ -33,7 +33,6 @@ struct CreationRules {
static typename std::enable_if<!has_static_new<U, Args...>::value, U*>::type New(Args&&... args) {
static_assert(!std::is_abstract<U>::value, "Cannot create a type which is abstract");
static_assert(!has_static_new<U, Args...>::value, "Can't inject member with arguments if it has a static new");
static_assert(!sizeof...(Args) || !has_simple_constructor<U>::value, "Can't inject member with arguments if it has a default constructor");

// Allocate slot first before registration
auto* pSpace = Allocate<U>(nullptr);
Expand Down
27 changes: 7 additions & 20 deletions autowiring/TypeUnifier.h
Expand Up @@ -12,42 +12,29 @@ class TypeUnifierComplex:
public TypeUnifier
{
public:
template<class Arg0, class... Args>
TypeUnifierComplex(Arg0&& arg0, Args&&... args) :
T(std::forward<Arg0>(arg0), std::forward<Args>(args)...)
template<class... Args>
TypeUnifierComplex(Args&&... args) :
T(std::forward<Args>(args)...)
{}
};

template<class T>
class TypeUnifierSimple:
public T,
public TypeUnifier
{};

/// <summary>
/// Utility class which allows us to either use the pure type T, or a unifier, as appropriate
/// </summary>
template<
class T,
bool inheritsObject = std::is_base_of<Object, T>::value,
bool hasSimpleCtor = has_simple_constructor<T>::value
bool inheritsObject = std::is_base_of<Object, T>::value
>
struct SelectTypeUnifier;

// Anyone already inheriting Object can just use Object
template<class T, bool hasSimpleCtor>
struct SelectTypeUnifier<T, true, hasSimpleCtor> {
typedef T type;
};

// If T has a simple ctor, we don't want to confuse the compiler with the complex TypeUnifier
template<class T>
struct SelectTypeUnifier<T, false, true> {
typedef TypeUnifierSimple<T> type;
struct SelectTypeUnifier<T, true> {
typedef T type;
};

// Otherwise, if there's a complex ctor, we have to use Args
template<class T>
struct SelectTypeUnifier<T, false, false> {
struct SelectTypeUnifier<T, false> {
typedef TypeUnifierComplex<T> type;
};
27 changes: 27 additions & 0 deletions src/autowiring/test/AutoConstructTest.cpp
@@ -0,0 +1,27 @@
#include "stdafx.h"

class AutoConstructTest:
public testing::Test
{};

class HasDefaultCtorAndOthers {
public:
HasDefaultCtorAndOthers(void) :
v(101)
{}
HasDefaultCtorAndOthers(int v) :
v(v)
{}

const int v;
};

TEST_F(AutoConstructTest, AutoConstructNoArgs) {
AutoConstruct<HasDefaultCtorAndOthers> hdcao;
ASSERT_EQ(101, hdcao->v) << "Default constructor was not called as expected";
}

TEST_F(AutoConstructTest, AutoConstructWithArgs) {
AutoConstruct<HasDefaultCtorAndOthers> hdcao(495);
ASSERT_EQ(495, hdcao->v) << "Constructor call was not made as expected";
}
1 change: 1 addition & 0 deletions src/autowiring/test/CMakeLists.txt
@@ -1,6 +1,7 @@
set(AutowiringTest_SRCS
AnySharedPointerTest.cpp
AutoAnchorTest.cpp
AutoConstructTest.cpp
AutoFilterTest.cpp
AutoInjectableTest.cpp
AutoPacketFactoryTest.cpp
Expand Down

0 comments on commit d8e84a3

Please sign in to comment.