Skip to content

Commit f8cac7f

Browse files
committed
Added standard_rules; a set of assertions against standard traits.
1 parent 3b53f3d commit f8cac7f

3 files changed

Lines changed: 333 additions & 0 deletions

File tree

Lines changed: 129 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,129 @@
1+
#pragma once
2+
3+
/**
4+
* This file contains a set of compile-time assertions in the form of consteval functions that are used to ensure a given type adhears to the respective rules.
5+
*
6+
* The expected use is to execute the respective function immediately following the type definition, storing the result in an unused value. This will result in the static_assert triggering if the rule
7+
* doesn't hold, while allowing the compiler to optimize away the variable if the rule does hold.
8+
*
9+
* Example usage:
10+
*
11+
* class EmptyType {};
12+
* [[maybe_unused]] bool _EmptyTypeIsDefaultConstructible = assert_is_default_constructible<EmptyType>();
13+
*/
14+
15+
#include <type_traits>
16+
17+
template<typename T> [[maybe_unused]] consteval bool assert_is_default_constructible()
18+
{
19+
#ifndef NON_FATAL_STANDARD_RULES
20+
static_assert(std::is_default_constructible_v<T>, "Type must be default constructible.");
21+
#endif
22+
return std::is_default_constructible_v<T>;
23+
}
24+
25+
template<typename T> [[maybe_unused]] consteval bool assert_is_trivially_constructible()
26+
{
27+
#ifndef NON_FATAL_STANDARD_RULES
28+
static_assert(std::is_trivially_constructible_v<T>, "Type must be trivially constructible.");
29+
#endif
30+
return std::is_trivially_constructible_v<T>;
31+
}
32+
33+
template<typename T> [[maybe_unused]] consteval bool assert_is_nothrow_default_constructible()
34+
{
35+
#ifndef NON_FATAL_STANDARD_RULES
36+
static_assert(std::is_nothrow_default_constructible_v<T>, "Type must be (nothrow) default constructible.");
37+
#endif
38+
return std::is_nothrow_default_constructible_v<T>;
39+
}
40+
41+
template<typename T> [[maybe_unused]] consteval bool assert_is_copyable()
42+
{
43+
#ifndef NON_FATAL_STANDARD_RULES
44+
static_assert(std::is_copy_constructible_v<T>, "Type must be copy constructible.");
45+
static_assert(std::is_copy_assignable_v<T>, "Type must be copy assignable.");
46+
#endif
47+
return std::is_copy_constructible_v<T> && std::is_copy_assignable_v<T>;
48+
}
49+
50+
template<typename T> [[maybe_unused]] consteval bool assert_is_trivially_copyable()
51+
{
52+
#ifndef NON_FATAL_STANDARD_RULES
53+
static_assert(std::is_trivially_copy_constructible_v<T>, "Type must be (trivially) copy constructible.");
54+
static_assert(std::is_trivially_copy_assignable_v<T>, "Type must be (trivially) copy assignable.");
55+
#endif
56+
return std::is_trivially_copy_constructible_v<T> && std::is_trivially_copy_assignable_v<T>;
57+
}
58+
59+
template<typename T> [[maybe_unused]] consteval bool assert_is_nothrow_copyable()
60+
{
61+
#ifndef NON_FATAL_STANDARD_RULES
62+
static_assert(std::is_nothrow_copy_constructible_v<T>, "Type must be (nothrow) copy constructible.");
63+
static_assert(std::is_nothrow_copy_assignable_v<T>, "Type must be (nothrow) copy assignable.");
64+
#endif
65+
return std::is_nothrow_copy_constructible_v<T> && std::is_nothrow_copy_assignable_v<T>;
66+
}
67+
68+
template<typename T> [[maybe_unused]] consteval bool assert_is_moveable()
69+
{
70+
#ifndef NON_FATAL_STANDARD_RULES
71+
static_assert(std::is_move_constructible_v<T>, "Type must be moveconstructible.");
72+
static_assert(std::is_move_assignable_v<T>, "Type must be move assignable.");
73+
#endif
74+
return std::is_move_constructible_v<T> && std::is_move_assignable_v<T>;
75+
}
76+
77+
template<typename T> [[maybe_unused]] consteval bool assert_is_trivially_moveable()
78+
{
79+
#ifndef NON_FATAL_STANDARD_RULES
80+
static_assert(std::is_trivially_move_constructible_v<T>, "Type must be (trivially) move constructible.");
81+
static_assert(std::is_trivially_move_assignable_v<T>, "Type must be (trivially) move assignable.");
82+
#endif
83+
return std::is_trivially_move_constructible_v<T> && std::is_trivially_move_assignable_v<T>;
84+
}
85+
86+
template<typename T> [[maybe_unused]] consteval bool assert_is_nothrow_moveable()
87+
{
88+
#ifndef NON_FATAL_STANDARD_RULES
89+
static_assert(std::is_nothrow_move_constructible_v<T>, "Type must be (nothrow) move constructible.");
90+
static_assert(std::is_nothrow_move_assignable_v<T>, "Type must be (nothrow) move assignable.");
91+
#endif
92+
return std::is_nothrow_move_constructible_v<T> && std::is_nothrow_move_assignable_v<T>;
93+
}
94+
95+
template<typename T> [[maybe_unused]] consteval bool assert_is_destructible()
96+
{
97+
#ifndef NON_FATAL_STANDARD_RULES
98+
static_assert(std::is_destructible_v<T>, "Type must be destructible.");
99+
#endif
100+
return std::is_destructible_v<T>;
101+
}
102+
103+
template<typename T> [[maybe_unused]] consteval bool assert_is_trivially_destructible()
104+
{
105+
#ifndef NON_FATAL_STANDARD_RULES
106+
static_assert(std::is_trivially_destructible_v<T>, "Type must be (trivially) destructible.");
107+
#endif
108+
return std::is_trivially_destructible_v<T>;
109+
}
110+
111+
template<typename T> [[maybe_unused]] consteval bool assert_is_nothrow_destructible()
112+
{
113+
#ifndef NON_FATAL_STANDARD_RULES
114+
static_assert(std::is_nothrow_destructible_v<T>, "Type must be (nothrow) destructible.");
115+
#endif
116+
return std::is_nothrow_destructible_v<T>;
117+
}
118+
119+
/**
120+
* Asserts that a type is trivial; i.e. is a scalar, or is trivially constructible.
121+
* For more, see https://en.cppreference.com/w/cpp/types/is_trivial
122+
*/
123+
template<typename T> [[maybe_unused]] consteval bool assert_is_trivial()
124+
{
125+
#ifndef NON_FATAL_STANDARD_RULES
126+
static_assert(std::is_trivial_v<T>, "Type must be a trivial type.");
127+
#endif
128+
return std::is_trivial_v<T>;
129+
}

test/CMakeLists.txt

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,22 @@ catch_discover_tests(
2424
.xml
2525
)
2626

27+
add_executable(standard_rules_tests "assertions/standard_rules_tests.cpp")
28+
target_link_libraries(standard_rules_tests PRIVATE project_options project_warnings catch_main)
29+
catch_discover_tests(
30+
standard_rules_tests
31+
TEST_PREFIX
32+
"standard_rules."
33+
REPORTER
34+
xml
35+
OUTPUT_DIR
36+
.
37+
OUTPUT_PREFIX
38+
"standard_rules."
39+
OUTPUT_SUFFIX
40+
.xml
41+
)
42+
2743
add_executable(has_function_tests "conditions/has_function_tests.cpp")
2844
target_link_libraries(has_function_tests PRIVATE project_options project_warnings catch_main)
2945
catch_discover_tests(
Lines changed: 188 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,188 @@
1+
#define NON_FATAL_STANDARD_RULES
2+
#include "code_library/assertions/standard_rules.hpp"
3+
4+
#include <catch2/catch.hpp>
5+
6+
#include <memory>
7+
8+
class EmptyType {};
9+
10+
class UnconstructibleType
11+
{
12+
UnconstructibleType() = delete;
13+
UnconstructibleType(const UnconstructibleType&) = delete;
14+
};
15+
16+
class EmptyTypeWithExplicitConstructor
17+
{
18+
public:
19+
EmptyTypeWithExplicitConstructor() {}
20+
};
21+
22+
class EmptyTypeWithExplicitNoexceptConstructor
23+
{
24+
public:
25+
EmptyTypeWithExplicitNoexceptConstructor() noexcept {}
26+
};
27+
28+
class CopyOnlyType
29+
{
30+
public:
31+
CopyOnlyType(const CopyOnlyType&) noexcept = default;
32+
CopyOnlyType& operator=(const CopyOnlyType&) noexcept = default;
33+
CopyOnlyType(CopyOnlyType&&) noexcept = delete;
34+
CopyOnlyType& operator=(CopyOnlyType&&) noexcept = delete;
35+
};
36+
37+
class MoveOnlyType
38+
{
39+
public:
40+
MoveOnlyType(const MoveOnlyType&) noexcept = delete;
41+
MoveOnlyType& operator=(const MoveOnlyType&) noexcept = delete;
42+
MoveOnlyType(MoveOnlyType&&) noexcept = default;
43+
MoveOnlyType& operator=(MoveOnlyType&&) noexcept = default;
44+
};
45+
46+
class UniquePtrType
47+
{
48+
private:
49+
std::unique_ptr<int> value_;
50+
};
51+
52+
TEST_CASE("Standard Rules can be enforced", "[standard_rules]")
53+
{
54+
SECTION("Types can be enforced to be constructible")
55+
{
56+
CHECK(assert_is_default_constructible<EmptyType>());
57+
CHECK(assert_is_trivially_constructible<EmptyType>());
58+
CHECK(assert_is_nothrow_default_constructible<EmptyType>());
59+
60+
CHECK(!assert_is_default_constructible<UnconstructibleType>());
61+
CHECK(!assert_is_trivially_constructible<UnconstructibleType>());
62+
CHECK(!assert_is_nothrow_default_constructible<UnconstructibleType>());
63+
64+
CHECK(assert_is_default_constructible<EmptyTypeWithExplicitConstructor>());
65+
CHECK(!assert_is_trivially_constructible<EmptyTypeWithExplicitConstructor>());
66+
CHECK(!assert_is_nothrow_default_constructible<EmptyTypeWithExplicitConstructor>());
67+
68+
CHECK(assert_is_default_constructible<EmptyTypeWithExplicitNoexceptConstructor>());
69+
CHECK(!assert_is_trivially_constructible<EmptyTypeWithExplicitNoexceptConstructor>());
70+
CHECK(assert_is_nothrow_default_constructible<EmptyTypeWithExplicitNoexceptConstructor>());
71+
72+
CHECK(!assert_is_default_constructible<CopyOnlyType>());
73+
CHECK(!assert_is_trivially_constructible<CopyOnlyType>());
74+
CHECK(!assert_is_nothrow_default_constructible<CopyOnlyType>());
75+
76+
CHECK(!assert_is_default_constructible<MoveOnlyType>());
77+
CHECK(!assert_is_trivially_constructible<MoveOnlyType>());
78+
CHECK(!assert_is_nothrow_default_constructible<MoveOnlyType>());
79+
80+
CHECK(assert_is_default_constructible<UniquePtrType>());
81+
CHECK(!assert_is_trivially_constructible<UniquePtrType>());
82+
CHECK(assert_is_nothrow_default_constructible<UniquePtrType>());
83+
}
84+
85+
SECTION("Types can be enforced to be copyable", "[standard_rules]")
86+
{
87+
CHECK(assert_is_copyable<EmptyType>());
88+
CHECK(assert_is_trivially_copyable<EmptyType>());
89+
CHECK(assert_is_nothrow_copyable<EmptyType>());
90+
91+
CHECK(!assert_is_copyable<UnconstructibleType>());
92+
CHECK(!assert_is_trivially_copyable<UnconstructibleType>());
93+
CHECK(!assert_is_nothrow_copyable<UnconstructibleType>());
94+
95+
CHECK(assert_is_copyable<EmptyTypeWithExplicitConstructor>());
96+
CHECK(assert_is_trivially_copyable<EmptyTypeWithExplicitConstructor>());
97+
CHECK(assert_is_nothrow_copyable<EmptyTypeWithExplicitConstructor>());
98+
99+
CHECK(assert_is_copyable<EmptyTypeWithExplicitNoexceptConstructor>());
100+
CHECK(assert_is_trivially_copyable<EmptyTypeWithExplicitNoexceptConstructor>());
101+
CHECK(assert_is_nothrow_copyable<EmptyTypeWithExplicitNoexceptConstructor>());
102+
103+
CHECK(assert_is_copyable<CopyOnlyType>());
104+
CHECK(assert_is_trivially_copyable<CopyOnlyType>());
105+
CHECK(assert_is_nothrow_copyable<CopyOnlyType>());
106+
107+
CHECK(!assert_is_copyable<MoveOnlyType>());
108+
CHECK(!assert_is_trivially_copyable<MoveOnlyType>());
109+
CHECK(!assert_is_nothrow_copyable<MoveOnlyType>());
110+
111+
CHECK(!assert_is_copyable<UniquePtrType>());
112+
CHECK(!assert_is_trivially_copyable<UniquePtrType>());
113+
CHECK(!assert_is_nothrow_copyable<UniquePtrType>());
114+
}
115+
116+
SECTION("Types can be enforced to be moveable", "[standard_rules]")
117+
{
118+
CHECK(assert_is_moveable<EmptyType>());
119+
CHECK(assert_is_trivially_moveable<EmptyType>());
120+
CHECK(assert_is_nothrow_moveable<EmptyType>());
121+
122+
CHECK(!assert_is_moveable<UnconstructibleType>());
123+
CHECK(!assert_is_trivially_moveable<UnconstructibleType>());
124+
CHECK(!assert_is_nothrow_moveable<UnconstructibleType>());
125+
126+
CHECK(assert_is_moveable<EmptyTypeWithExplicitConstructor>());
127+
CHECK(assert_is_trivially_moveable<EmptyTypeWithExplicitConstructor>());
128+
CHECK(assert_is_nothrow_moveable<EmptyTypeWithExplicitConstructor>());
129+
130+
CHECK(assert_is_moveable<EmptyTypeWithExplicitNoexceptConstructor>());
131+
CHECK(assert_is_trivially_moveable<EmptyTypeWithExplicitNoexceptConstructor>());
132+
CHECK(assert_is_nothrow_moveable<EmptyTypeWithExplicitNoexceptConstructor>());
133+
134+
CHECK(!assert_is_moveable<CopyOnlyType>());
135+
CHECK(!assert_is_trivially_moveable<CopyOnlyType>());
136+
CHECK(!assert_is_nothrow_moveable<CopyOnlyType>());
137+
138+
CHECK(assert_is_moveable<MoveOnlyType>());
139+
CHECK(assert_is_trivially_moveable<MoveOnlyType>());
140+
CHECK(assert_is_nothrow_moveable<MoveOnlyType>());
141+
142+
CHECK(assert_is_moveable<UniquePtrType>());
143+
CHECK(!assert_is_trivially_moveable<UniquePtrType>());
144+
CHECK(assert_is_nothrow_moveable<UniquePtrType>());
145+
}
146+
147+
SECTION("Types can be enforced to be destructible", "[standard_rules]")
148+
{
149+
CHECK(assert_is_destructible<EmptyType>());
150+
CHECK(assert_is_trivially_destructible<EmptyType>());
151+
CHECK(assert_is_nothrow_destructible<EmptyType>());
152+
153+
CHECK(assert_is_destructible<UnconstructibleType>());
154+
CHECK(assert_is_trivially_destructible<UnconstructibleType>());
155+
CHECK(assert_is_nothrow_destructible<UnconstructibleType>());
156+
157+
CHECK(assert_is_destructible<EmptyTypeWithExplicitConstructor>());
158+
CHECK(assert_is_trivially_destructible<EmptyTypeWithExplicitConstructor>());
159+
CHECK(assert_is_nothrow_destructible<EmptyTypeWithExplicitConstructor>());
160+
161+
CHECK(assert_is_destructible<EmptyTypeWithExplicitNoexceptConstructor>());
162+
CHECK(assert_is_trivially_destructible<EmptyTypeWithExplicitNoexceptConstructor>());
163+
CHECK(assert_is_nothrow_destructible<EmptyTypeWithExplicitNoexceptConstructor>());
164+
165+
CHECK(assert_is_destructible<CopyOnlyType>());
166+
CHECK(assert_is_trivially_destructible<CopyOnlyType>());
167+
CHECK(assert_is_nothrow_destructible<CopyOnlyType>());
168+
169+
CHECK(assert_is_destructible<MoveOnlyType>());
170+
CHECK(assert_is_trivially_destructible<MoveOnlyType>());
171+
CHECK(assert_is_nothrow_destructible<MoveOnlyType>());
172+
173+
CHECK(assert_is_destructible<UniquePtrType>());
174+
CHECK(!assert_is_trivially_destructible<UniquePtrType>());
175+
CHECK(assert_is_nothrow_destructible<UniquePtrType>());
176+
}
177+
178+
SECTION("Types can be enforced to be trivial", "[standard_rules]")
179+
{
180+
CHECK(assert_is_trivial<EmptyType>());
181+
CHECK(assert_is_trivial<UnconstructibleType>());
182+
CHECK(!assert_is_trivial<EmptyTypeWithExplicitConstructor>());
183+
CHECK(!assert_is_trivial<EmptyTypeWithExplicitNoexceptConstructor>());
184+
CHECK(!assert_is_trivial<CopyOnlyType>());
185+
CHECK(!assert_is_trivial<MoveOnlyType>());
186+
CHECK(!assert_is_trivial<UniquePtrType>());
187+
}
188+
}

0 commit comments

Comments
 (0)