Skip to content

Commit fa6b302

Browse files
committed
Handles are valid upon construction
1 parent 5e7cddc commit fa6b302

File tree

5 files changed

+24
-42
lines changed

5 files changed

+24
-42
lines changed

phlex/model/handle.hpp

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -30,31 +30,22 @@ namespace phlex::experimental {
3030
using const_reference = value_type const&;
3131
using const_pointer = value_type const*;
3232

33-
handle() = default;
34-
3533
template <typename U>
36-
explicit handle(product<U> const& prod, level_id const& id = level_id::base())
34+
explicit handle(U const* prod, level_id const& id)
3735
requires detail::same_handle_type<T, U>
38-
: rep_{&prod.obj}, id_{&id}
36+
: rep_{prod}, id_{&id}
3937
{
4038
}
4139

42-
explicit handle(std::variant<const_pointer, err_t> maybe_product, level_id const& id) :
43-
rep_{std::move(maybe_product)}, id_{&id}
40+
template <typename U>
41+
explicit handle(product<U> const& prod, level_id const& id = level_id::base())
42+
requires detail::same_handle_type<T, U>
43+
: handle{&prod.obj, id}
4444
{
4545
}
4646

47-
explicit handle(std::string err_msg, level_id const& id) : rep_{std::move(err_msg)}, id_{&id} {}
48-
49-
const_pointer operator->() const
50-
{
51-
if (auto const* err = get_if<err_t>(&rep_)) {
52-
throw std::runtime_error(*err);
53-
}
54-
return get<const_pointer>(rep_);
55-
}
56-
[[nodiscard]] const_reference operator*() const { return *operator->(); }
57-
explicit operator bool() const noexcept { return get_if<const_pointer>(&rep_) != nullptr; }
47+
const_pointer operator->() const noexcept { return rep_; }
48+
[[nodiscard]] const_reference operator*() const noexcept { return *operator->(); }
5849
operator const_reference() const noexcept { return operator*(); }
5950
operator const_pointer() const noexcept { return operator->(); }
6051

@@ -71,9 +62,8 @@ namespace phlex::experimental {
7162
}
7263

7364
private:
74-
std::variant<const_pointer, err_t> rep_{"Cannot dereference empty handle of type '" +
75-
boost::core::demangle(typeid(T).name()) + "'."};
76-
class level_id const* id_;
65+
const_pointer rep_{nullptr};
66+
class level_id const* id_{nullptr};
7767
};
7868

7969
template <typename T>

phlex/model/products.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,12 @@ namespace phlex::experimental {
1313
products::const_iterator products::begin() const noexcept { return products_.begin(); }
1414
products::const_iterator products::end() const noexcept { return products_.end(); }
1515

16-
std::string products::error_message(std::string const& product_name,
17-
char const* requested_type,
18-
char const* available_type)
16+
void products::throw_mismatched_type(std::string const& product_name,
17+
char const* requested_type,
18+
char const* available_type)
1919
{
20-
return "Cannot get product '" + product_name + "' with type '" +
21-
boost::core::demangle(requested_type) + "' -- must specify type '" +
22-
boost::core::demangle(available_type) + "'.";
20+
throw std::runtime_error("Cannot get product '" + product_name + "' with type '" +
21+
boost::core::demangle(requested_type) + "' -- must specify type '" +
22+
boost::core::demangle(available_type) + "'.");
2323
}
2424
}

phlex/model/products.hpp

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -69,11 +69,11 @@ namespace phlex::experimental {
6969
}
7070

7171
template <typename T>
72-
std::variant<T const*, std::string> get(std::string const& product_name) const
72+
T const* get(std::string const& product_name) const
7373
{
7474
auto it = products_.find(product_name);
7575
if (it == cend(products_)) {
76-
return "No product exists with the name '" + product_name + "'.";
76+
throw std::runtime_error("No product exists with the name '" + product_name + "'.");
7777
}
7878

7979
// Should be able to use dynamic_cast a la:
@@ -89,17 +89,18 @@ namespace phlex::experimental {
8989
if (std::strcmp(typeid(T).name(), available_product->type().name()) == 0) {
9090
return &reinterpret_cast<product<T> const*>(available_product)->obj;
9191
}
92-
return error_message(product_name, typeid(T).name(), available_product->type().name());
92+
93+
throw_mismatched_type(product_name, typeid(T).name(), available_product->type().name());
9394
}
9495

9596
bool contains(std::string const& product_name) const;
9697
const_iterator begin() const noexcept;
9798
const_iterator end() const noexcept;
9899

99100
private:
100-
static std::string error_message(std::string const& product_name,
101-
char const* requested_type,
102-
char const* available_type);
101+
static void throw_mismatched_type [[noreturn]] (std::string const& product_name,
102+
char const* requested_type,
103+
char const* available_type);
103104

104105
collection_t products_;
105106
};

test/product_handle.cpp

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,12 +34,6 @@ TEST_CASE("Can only create handles with compatible types", "[data model]")
3434

3535
TEST_CASE("Handle type conversions (run-time checks)", "[data model]")
3636
{
37-
handle<double> empty;
38-
CHECK(not empty);
39-
CHECK_THROWS_WITH(
40-
*empty,
41-
Catch::Matchers::ContainsSubstring("Cannot dereference empty handle of type 'double'."));
42-
4337
product<int> const number{3};
4438
handle const h{number};
4539
CHECK(handle<int const>{number} == h);

test/product_store.cpp

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,9 @@ TEST_CASE("Product store insertion", "[data model]")
2121
Catch::Matchers::ContainsSubstring(
2222
"Cannot get product 'number' with type 'double' -- must specify type 'int'."));
2323

24-
auto invalid_handle = store->get_handle<int>("wrong_key");
25-
CHECK(!invalid_handle);
2624
auto const matcher =
2725
Catch::Matchers::ContainsSubstring("No product exists with the name 'wrong_key'.");
28-
CHECK_THROWS_WITH(*invalid_handle, matcher);
29-
CHECK_THROWS_WITH(invalid_handle.operator->(), matcher);
26+
CHECK_THROWS_WITH(store->get_handle<int>("wrong_key"), matcher);
3027

3128
CHECK(store->get_product<int>("number") == number);
3229

0 commit comments

Comments
 (0)