Skip to content

Commit bd57c40

Browse files
committed
Allow CTAD for fine::Ok and fine::Error
Class Template Argument Deduction allows class templates to be inferred from constructor arguments, which removes the need for `fine::ok` and `fine::error` as special factory functions.
1 parent 662c321 commit bd57c40

File tree

3 files changed

+29
-50
lines changed

3 files changed

+29
-50
lines changed

README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -475,22 +475,22 @@ types for this purpose, along with their respective factories `fine::ok` and
475475
476476
```c++
477477
fine::Ok<> example() {
478-
return fine::ok();
478+
return fine::Ok();
479479
}
480480
// :ok
481481
482482
fine::Ok<int64_t> example() {
483-
return fine::ok(1); // implicit conversion
483+
return fine::Ok(1); // implicit conversion
484484
}
485485
// {:ok, 1}
486486
487487
fine::Error<> example() {
488-
return fine::error();
488+
return fine::Error();
489489
}
490490
// :error
491491
492492
fine::Error<std::string> example() {
493-
return fine::error("something went wrong"); // implicit conversion
493+
return fine::Error("something went wrong"); // implicit conversion
494494
}
495495
// {:error, "something went wrong"}
496496
```
@@ -501,10 +501,10 @@ a NIF may return:
501501
```c++
502502
std::variant<fine::Ok<int64_t>, fine::Error<std::string>> find_meaning(ErlNifEnv *env) {
503503
if (...) {
504-
return fine::error("something went wrong");
504+
return fine::Error("something went wrong");
505505
}
506506
507-
return fine::ok(42);
507+
return fine::Ok(42);
508508
}
509509
```
510510

c_include/fine.hpp

Lines changed: 14 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -142,38 +142,27 @@ class Term {
142142
ERL_NIF_TERM term;
143143
};
144144

145-
namespace __private__ {
146-
template <class T> struct UnwrapRefwrapper {
147-
using type = T;
148-
};
149-
150-
template <class T> struct UnwrapRefwrapper<std::reference_wrapper<T>> {
151-
using type = T &;
152-
};
153-
154-
template <class T>
155-
using UnwrapDecayType =
156-
typename UnwrapRefwrapper<typename std::decay<T>::type>::type;
157-
} // namespace __private__
158-
159145
// Represents a `:ok` tagged tuple, useful as a NIF result.
160146
template <typename... Args> class Ok {
161147
public:
162148
using Items = std::tuple<Args...>;
163149

164-
Ok(Items &&items) : m_items(std::forward<Items>(items)) {}
150+
template <typename = std::enable_if_t<std::is_default_constructible_v<Items>>>
151+
Ok() : m_items() {}
152+
153+
explicit Ok(Args... items) : m_items{std::move(items)...} {}
165154

166155
template <typename... UArgs>
167-
Ok(const Ok<UArgs...> &other) : m_items{other.items()} {}
156+
Ok(const Ok<UArgs...> &other) : m_items(other.items()) {}
168157

169158
template <typename... UArgs>
170-
Ok(Ok<UArgs...> &&other) : m_items{other.items()} {}
159+
Ok(Ok<UArgs...> &&other) : m_items(std::move(other).items()) {}
171160

172161
const Items &items() const & noexcept { return m_items; }
173162

174163
Items &items() & noexcept { return m_items; }
175164

176-
Items &&items() && noexcept { return m_items; }
165+
Items &&items() && noexcept { return std::move(m_items); }
177166

178167
private:
179168
std::tuple<Args...> m_items;
@@ -184,37 +173,27 @@ template <typename... Args> class Error {
184173
public:
185174
using Items = std::tuple<Args...>;
186175

187-
Error(Items &&items) : m_items(std::forward<Items>(items)) {}
176+
template <typename = std::enable_if_t<std::is_default_constructible_v<Items>>>
177+
Error() : m_items() {}
178+
179+
explicit Error(Args... items) : m_items{std::move(items)...} {}
188180

189181
template <typename... UArgs>
190-
Error(const Error<UArgs...> &other) : m_items{other.items()} {}
182+
Error(const Error<UArgs...> &other) : m_items(other.items()) {}
191183

192184
template <typename... UArgs>
193-
Error(Error<UArgs...> &&other) : m_items{other.items()} {}
185+
Error(Error<UArgs...> &&other) : m_items(std::move(other).items()) {}
194186

195187
const Items &items() const & noexcept { return m_items; }
196188

197189
Items &items() & noexcept { return m_items; }
198190

199-
Items &&items() && noexcept { return m_items; }
191+
Items &&items() && noexcept { return std::move(m_items); }
200192

201193
private:
202194
std::tuple<Args...> m_items;
203195
};
204196

205-
template <typename... Args>
206-
inline static Ok<__private__::UnwrapDecayType<Args>...> ok(Args &&...args) {
207-
return Ok<__private__::UnwrapDecayType<Args>...>{
208-
std::make_tuple(std::forward<Args>(args)...)};
209-
}
210-
211-
template <typename... Args>
212-
inline static Error<__private__::UnwrapDecayType<Args>...>
213-
error(Args &&...args) {
214-
return Error<__private__::UnwrapDecayType<Args>...>{
215-
std::make_tuple(std::forward<Args>(args)...)};
216-
}
217-
218197
namespace __private__ {
219198
template <typename T> struct ResourceWrapper {
220199
T resource;

test/c_src/finest.cpp

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -144,32 +144,32 @@ FINE_NIF(codec_tuple_int64_and_string, 0);
144144

145145
Result<std::string, int64_t> codec_result_string_int64_ok(ErlNifEnv *,
146146
std::string term) {
147-
return fine::ok(term);
147+
return fine::Ok(term);
148148
}
149149
FINE_NIF(codec_result_string_int64_ok, 0);
150150

151151
Result<std::string, int64_t> codec_result_string_int64_error(ErlNifEnv *,
152152
int64_t term) {
153-
return fine::error(term);
153+
return fine::Error(term);
154154
}
155155
FINE_NIF(codec_result_string_int64_error, 0);
156156

157157
Result<std::string, int64_t>
158158
codec_result_string_int64_ok_conversion(ErlNifEnv *) {
159-
return fine::ok("fine");
159+
return fine::Ok("fine");
160160
}
161161
FINE_NIF(codec_result_string_int64_ok_conversion, 0);
162162

163163
Result<std::string, int64_t>
164164
codec_result_string_int64_error_conversion(ErlNifEnv *) {
165165
uint16_t result = 42;
166-
return fine::error(result);
166+
return fine::Error(result);
167167
}
168168
FINE_NIF(codec_result_string_int64_error_conversion, 0);
169169

170170
std::variant<fine::Ok<int64_t, std::string>, fine::Error<>>
171171
codec_result_int64_string_void_ok_conversion(ErlNifEnv *) {
172-
return fine::ok(static_cast<int32_t>(201702), "c++17");
172+
return fine::Ok(static_cast<int32_t>(201702), "c++17");
173173
}
174174
FINE_NIF(codec_result_int64_string_void_ok_conversion, 0);
175175

@@ -197,19 +197,19 @@ FINE_NIF(codec_struct, 0);
197197
ExError codec_struct_exception(ErlNifEnv *, ExError term) { return term; }
198198
FINE_NIF(codec_struct_exception, 0);
199199

200-
fine::Ok<> codec_ok_empty(ErlNifEnv *) { return fine::ok(); }
200+
fine::Ok<> codec_ok_empty(ErlNifEnv *) { return fine::Ok(); }
201201
FINE_NIF(codec_ok_empty, 0);
202202

203203
fine::Ok<int64_t> codec_ok_int64(ErlNifEnv *, int64_t term) {
204-
return fine::ok(term);
204+
return fine::Ok(term);
205205
}
206206
FINE_NIF(codec_ok_int64, 0);
207207

208-
fine::Error<> codec_error_empty(ErlNifEnv *) { return fine::error(); }
208+
fine::Error<> codec_error_empty(ErlNifEnv *) { return fine::Error(); }
209209
FINE_NIF(codec_error_empty, 0);
210210

211211
fine::Error<std::string> codec_error_string(ErlNifEnv *, std::string term) {
212-
return fine::error(term);
212+
return fine::Error(term);
213213
}
214214
FINE_NIF(codec_error_string, 0);
215215

0 commit comments

Comments
 (0)