aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--CMakeLists.txt1
-rw-r--r--include/newtype/new_type.hpp4
-rw-r--r--test/include/conversion_suite.hpp11
-rw-r--r--test/include/kawaii.hpp5
-rw-r--r--test/src/conversion_suite.cpp201
-rw-r--r--test/src/driver.cpp6
6 files changed, 221 insertions, 7 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 070fdb6..9977012 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -50,6 +50,7 @@ if(BUILD_TESTING)
"${PROJECT_SOURCE_DIR}/test/src/driver.cpp"
"${PROJECT_SOURCE_DIR}/test/src/derivation_clause_suite.cpp"
+ "${PROJECT_SOURCE_DIR}/test/src/conversion_suite.cpp"
"${PROJECT_SOURCE_DIR}/test/src/new_type_constructor_suite.cpp"
)
diff --git a/include/newtype/new_type.hpp b/include/newtype/new_type.hpp
index 68a22dd..67e29c3 100644
--- a/include/newtype/new_type.hpp
+++ b/include/newtype/new_type.hpp
@@ -39,7 +39,7 @@ namespace nt
/**
* Retrieve the base type value contained in this @p new_type
*/
- auto constexpr decay() const noexcept -> BaseType
+ auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v<BaseType>) -> BaseType
{
return m_value;
}
@@ -75,7 +75,7 @@ namespace nt
/**
* Retrieve the base type value contained in this @p new_type
*/
- auto constexpr decay() const noexcept -> BaseType
+ auto constexpr decay() const noexcept(std::is_nothrow_copy_constructible_v<BaseType>) -> BaseType
{
return m_value;
}
diff --git a/test/include/conversion_suite.hpp b/test/include/conversion_suite.hpp
new file mode 100644
index 0000000..8b9c337
--- /dev/null
+++ b/test/include/conversion_suite.hpp
@@ -0,0 +1,11 @@
+#ifndef NEWTYPE_TEST_CONVERSION_SUITE_HPP
+#define NEWTYPE_TEST_CONVERSION_SUITE_HPP
+
+#include <cute/cute_suite.h>
+
+#include <string>
+#include <utility>
+
+auto conversion_suite() -> std::pair<cute::suite, std::string>;
+
+#endif \ No newline at end of file
diff --git a/test/include/kawaii.hpp b/test/include/kawaii.hpp
index 787f38a..69da012 100644
--- a/test/include/kawaii.hpp
+++ b/test/include/kawaii.hpp
@@ -17,7 +17,7 @@ namespace nt::test
namespace impl
{
auto constexpr prepositions = std::array{"a", "an", "and", "as", "at", "by", "for", "in", "of", "on", "or", "the", "to"};
-
+ auto constexpr keywords = std::array{"noexcept"};
auto constexpr type_names = std::array{"new_type", "derivation_clause"};
auto inline replace_template_argument_syntax(std::string const & name) -> std::string
@@ -103,8 +103,9 @@ namespace nt::test
while (stream >> word && word != "[")
{
auto is_preposition = std::find(cbegin(prepositions), cend(prepositions), word) != cend(prepositions);
+ auto is_keyword = std::find(cbegin(keywords), cend(keywords), word) != cend(keywords);
auto is_type_name = std::find(cbegin(type_names), cend(type_names), word) != cend(type_names);
- if ((!is_preposition || buffer.empty()) && !is_type_name)
+ if ((!(is_preposition || is_keyword) || buffer.empty()) && !is_type_name)
{
word.front() = std::toupper(word.front());
}
diff --git a/test/src/conversion_suite.cpp b/test/src/conversion_suite.cpp
new file mode 100644
index 0000000..b60a611
--- /dev/null
+++ b/test/src/conversion_suite.cpp
@@ -0,0 +1,201 @@
+#include "conversion_suite.hpp"
+
+#include "kawaii.hpp"
+#include "newtype/derivable.hpp"
+#include "newtype/deriving.hpp"
+#include "newtype/new_type.hpp"
+
+#include <cute/cute.h>
+
+#include <algorithm>
+#include <iterator>
+#include <limits>
+#include <random>
+#include <string>
+#include <type_traits>
+#include <vector>
+
+inline namespace traits_extensions
+{
+
+ template<typename To, typename From, typename = void>
+ struct is_implicitly_convertible : std::false_type
+ {
+ };
+
+ template<typename To, typename From>
+ struct is_implicitly_convertible<To, From, std::void_t<decltype(std::declval<To &>() = std::declval<From &>())>> : std::true_type
+ {
+ };
+
+ template<typename To, typename From>
+ auto constexpr is_implicitly_convertible_v = is_implicitly_convertible<To, From>::value;
+
+} // namespace traits_extensions
+
+inline namespace ddt_support
+{
+
+ template<typename T>
+ struct datum
+ {
+ T value;
+ cute::test_failure failure;
+ };
+
+ template<typename ValueType>
+ auto generate_test_set(std::size_t size) -> std::vector<datum<ValueType>>
+ {
+ auto device = std::random_device{};
+ auto generator = std::mt19937{device()};
+ auto distribution = [&] {
+ auto min = std::numeric_limits<ValueType>::min();
+ auto max = std::numeric_limits<ValueType>::max();
+ if constexpr (std::is_floating_point_v<ValueType>)
+ {
+ return std::uniform_real_distribution<ValueType>(min, max);
+ }
+ else
+ {
+ return std::uniform_int_distribution<ValueType>(min, max);
+ }
+ }();
+
+ auto data = std::vector<datum<ValueType>>{};
+ generate_n(std::back_inserter(data), size, [&] {
+ auto point = distribution(generator);
+ return datum<ValueType>{point, DDT()};
+ });
+ return data;
+ }
+
+} // namespace ddt_support
+
+inline namespace implicit_conversion_tests
+{
+
+ template<typename T>
+ auto a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type() -> void
+ {
+ using type_alias = nt::new_type<T, struct conversion_test_1_tag>;
+ ASSERT(!(is_implicitly_convertible_v<T, type_alias>));
+ }
+
+ template<typename T>
+ auto a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type() -> void
+ {
+ using type_alias = nt::new_type<T, struct conversion_test_2_tag, deriving(nt::ImplicitConversion)>;
+ ASSERT((is_implicitly_convertible_v<T, type_alias>));
+ }
+
+} // namespace implicit_conversion_tests
+
+inline namespace decay_tests
+{
+
+ template<typename T>
+ auto decay_on_a_new__type_has_a_return_type_equal_to_the_base_type() -> void
+ {
+ using type_alias = nt::new_type<T, struct conversion_test_3_tag>;
+ ASSERT((std::is_same_v<T, decltype(std::declval<type_alias &>().decay())>));
+ }
+
+ template<typename T>
+ auto decay_on_a_new__type_returns_the_underlying_value() -> void
+ {
+ using type_alias = nt::new_type<T, struct conversion_test_4_tag>;
+ auto data = generate_test_set<T>(2 << 16);
+ for_each(begin(data), end(data), [](auto & test) { ASSERT_EQUAL_DDT(test.value, type_alias{test.value}.decay(), test.failure); });
+ }
+
+} // namespace decay_tests
+
+inline namespace decay_noexcept_tests
+{
+
+ auto decay_on_a_new__type_is_noexcept_if_the_base_type_can_be_copied_without_throwing() -> void
+ {
+ static_assert(std::is_nothrow_copy_constructible_v<int>, "Sanity check");
+ using type_alias = nt::new_type<int, struct conversion_test_5_tag>;
+ ASSERT(noexcept(type_alias{}.decay()));
+ }
+
+ auto decay_on_a_new__type_is_not_noexcept_if_the_base_type_can_be_not_copied_without_throwing() -> void
+ {
+ struct strange_type
+ {
+ strange_type() = default;
+ strange_type(strange_type const &) noexcept(false)
+ {
+ }
+ };
+
+ static_assert(!std::is_nothrow_copy_constructible_v<strange_type>, "Sanity check");
+ using type_alias = nt::new_type<strange_type, struct conversion_test_6_tag>;
+ ASSERT(!noexcept(type_alias{}.decay()));
+ }
+
+} // namespace decay_noexcept_tests
+
+inline namespace conversion_operator_noexcept_tests
+{
+
+ auto new__type_conversion_operator_is_noexcept_if_the_base_type_can_be_copied_without_throwing() -> void
+ {
+ static_assert(std::is_nothrow_copy_constructible_v<int>, "Sanity check");
+ using type_alias = nt::new_type<int, struct conversion_test_5_tag>;
+ ASSERT(noexcept(static_cast<int>(type_alias{})));
+ }
+
+ auto new__type_conversion_operator_is_not_noexcept_if_the_base_type_can_not_be_copied_without_throwing() -> void
+ {
+ struct strange_type
+ {
+ strange_type() = default;
+ strange_type(strange_type const &) noexcept(false)
+ {
+ }
+ };
+
+ static_assert(!std::is_nothrow_copy_constructible_v<strange_type>, "Sanity check");
+ using type_alias = nt::new_type<strange_type, struct conversion_test_5_tag>;
+ ASSERT(!noexcept(static_cast<strange_type>(type_alias{})));
+ }
+
+} // namespace conversion_operator_noexcept_tests
+
+auto conversion_suite() -> std::pair<cute::suite, std::string>
+{
+ return {{
+ /// Implicit Conversion Tests
+ KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<bool>),
+ KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<char>),
+ KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<int>),
+ KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<double>),
+ KAWAII(a_new__type_without_deriving_implicit_conversion_is_not_implicitly_convertible_to_the_base_type<std::string>),
+ KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<bool>),
+ KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<char>),
+ KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<int>),
+ KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<double>),
+ KAWAII(a_new__type_with_deriving_implicit_conversion_is_implicitly_convertible_to_the_base_type<std::string>),
+
+ /// Decay Tests
+ KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<bool>),
+ KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<char>),
+ KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<int>),
+ KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<double>),
+ KAWAII(decay_on_a_new__type_has_a_return_type_equal_to_the_base_type<std::string>),
+ KAWAII(decay_on_a_new__type_returns_the_underlying_value<char>),
+ KAWAII(decay_on_a_new__type_returns_the_underlying_value<int>),
+ KAWAII(decay_on_a_new__type_returns_the_underlying_value<double>),
+
+ /// Decay noexcept Tests
+ KAWAII(decay_on_a_new__type_is_noexcept_if_the_base_type_can_be_copied_without_throwing),
+ KAWAII(decay_on_a_new__type_is_not_noexcept_if_the_base_type_can_be_not_copied_without_throwing),
+
+ /// Conversion Operator noexcept Tests
+ KAWAII(new__type_conversion_operator_is_noexcept_if_the_base_type_can_be_copied_without_throwing),
+ KAWAII(new__type_conversion_operator_is_not_noexcept_if_the_base_type_can_not_be_copied_without_throwing),
+ },
+ "Conversion Tests"};
+} \ No newline at end of file
diff --git a/test/src/driver.cpp b/test/src/driver.cpp
index 22e1ab9..6c1ae7d 100644
--- a/test/src/driver.cpp
+++ b/test/src/driver.cpp
@@ -1,3 +1,4 @@
+#include "conversion_suite.hpp"
#include "derivation_clause_suite.hpp"
#include "new_type_constructor_suite.hpp"
@@ -27,9 +28,7 @@ auto get_test_selectors(suite_list const & suites) -> std::vector<std::string>
for_each(cbegin(suites), cend(suites), [&](auto descriptor) {
auto const & [suite, name] = descriptor;
- transform(cbegin(suite), cend(suite), std::back_inserter(selectors), [&, name = name](auto test) {
- return name + "#" + test.name();
- });
+ transform(cbegin(suite), cend(suite), std::back_inserter(selectors), [&, name = name](auto test) { return name + "#" + test.name(); });
});
return selectors;
@@ -51,6 +50,7 @@ int main(int argc, char ** argv)
auto suites = std::vector{
derivation_clause_suite(),
new_type_constructor_suite(),
+ conversion_suite(),
};
auto selectors = get_test_selectors(suites);