Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fix has_static_new #1013

Merged
merged 7 commits into from
May 20, 2017
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -45,3 +45,5 @@ autowiring.kdev4
autowiring.VC.db
.vscode
AutowiringVersion.h

*.VC.db*
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

`Autowiring.VC.db is already listed above though?

Or if the intent here is the trailing asterisk, are there circumstances when it makes a db1, db2 file?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, 2017 adds several extensions.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see now. I have Browse.VC.db and Solution.VC.db{,-shm,-wal}.

Should remove the now-redundant autowiring.VC.db above then?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yep

55 changes: 11 additions & 44 deletions src/autowiring/has_static_new.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,51 +5,18 @@

namespace autowiring {

/// <summary>
/// Utility helper structure for types which have a factory New routine
/// </summary>
/// <remarks>
/// A factory New routine is malformed when the return type is not implicitly castable to type T
/// </remarks>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should keep the comments? I found the <remarks> line useful initially.

template<class T, class Selector, class... Args>
struct has_well_formed_static_new {
static const bool value = std::is_convertible<
decltype(
T::New(
std::declval<Args>()...
)
),
T*
>::value;
};

template<class T, class... Args>
struct has_well_formed_static_new<T, std::false_type, Args...> {
static const bool value = false;
};

template<typename T, typename... Args>
struct has_static_new
template <class T, typename... Args>
class has_static_new
{
template<class U>
static std::true_type select(decltype(U::New((Args&&)*(Args*)nullptr...))*);

template<class U>
static std::false_type select(...);

static const bool value = has_well_formed_static_new<T, decltype(select<T>(nullptr)), Args...>::value;
};

template<typename T>
struct has_static_new<T>
{
template<class U>
static std::true_type select(decltype(U::New())*);

template<class U>
static std::false_type select(...);

static const bool value = has_well_formed_static_new<T, decltype(select<T>(nullptr))>::value;
template<class U, class = typename std::enable_if<
std::is_function<decltype(U::New(std::declval<Args>()...))(Args...)>::value &&
std::is_convertible<decltype(U::New(std::declval<Args>()...)), T*>::value
>::type>
static std::true_type check(void*);
template <class...>
static std::false_type check(...);
public:
static const bool value = decltype(check<T>(nullptr))::value;
};

}
67 changes: 67 additions & 0 deletions src/autowiring/test/AutoConstructTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ namespace {
};
}

static_assert(
autowiring::select_strategy<HasDefaultCtorAndOthers, int>::value == autowiring::construction_strategy::standard,
"Construction strategy incorrectly inferred"
);

TEST_F(AutoConstructTest, AutoConstructNoArgs) {
AutoConstruct<HasDefaultCtorAndOthers> hdcao;
ASSERT_EQ(101, hdcao->v) << "Default constructor was not called as expected";
Expand Down Expand Up @@ -102,3 +107,65 @@ TEST_F(AutoConstructTest, FactoryNewPrivateCtor) {
ASSERT_NE(nullptr, mpcc.get()) << "Null not expected as a return type from a factory new construction";
ASSERT_EQ(1002, mpcc->ival) << "Correct ctor was not invoked on a type with a private ctor";
}

namespace {
class MyPrivateCtorStringClass :
public CoreObject
{
MyPrivateCtorStringClass(void) :
istr("default_string")
{}
MyPrivateCtorStringClass(const char* istr) :
istr(istr)
{}

public:
const char* istr;

static MyPrivateCtorStringClass* New(const char* str) {
return new MyPrivateCtorStringClass{ str };
}
};
}

static_assert(
autowiring::has_static_new<MyPrivateCtorStringClass, decltype("")>::value,
"Failed to find factory new on a type that carries it"
);
static_assert(
autowiring::select_strategy<MyPrivateCtorStringClass, decltype("")>::value == autowiring::construction_strategy::factory_new,
"Construction strategy incorrectly inferred"
);
static_assert(
!std::is_constructible<MyPrivateCtorStringClass>::value,
"Type reported as being constructable when it was not"
);
static_assert(
!autowiring::has_simple_constructor<MyPrivateCtorStringClass>::value,
"Simple constructor detected when said constructor should have been private"
);

TEST_F(AutoConstructTest, FactoryNewPrivateStringCtor) {
AutoConstruct<MyPrivateCtorStringClass> mpcc{ "a new string" };
ASSERT_NE(nullptr, mpcc.get()) << "Null not expected as a return type from a factory new construction";
ASSERT_STREQ("a new string", mpcc->istr) << "Correct ctor was not invoked on a type with a private ctor";
}

class MultiStaticNew : public CoreObject {
MultiStaticNew() {}
public:
static char* New() { return nullptr; }
static MultiStaticNew* New(int x) { return nullptr; }
};
static_assert(
!autowiring::has_static_new<MultiStaticNew>::value,
"Found a bad static new"
);
static_assert(
autowiring::has_static_new<MultiStaticNew, int>::value,
"Failed to find a good static new override"
);

TEST_F(AutoConstructTest, MultiStaticNewTest) {
AutoConstruct<MultiStaticNew> badstatic{ 1 };
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

missing newline at EOF

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This var is named badstatic. However, it looks like the good one?