1212#include < stdexcept>
1313#include < string>
1414#include < system_error>
15+ #include < tuple>
1516
1617#include < libpmemobj/atomic_base.h>
1718#include < libpmemobj/base.h>
1819
20+ #include < libpmemobj++/detail/integer_sequence.hpp>
21+
1922namespace pmem
2023{
2124
@@ -35,14 +38,39 @@ errormsg(void)
3538#endif
3639}
3740
41+ /* *
42+ * Helper for exception_with_errormsg.
43+ *
44+ * Accepts tuple with arguments and index_sequence which correspond
45+ * to all but last argument. The last element in tuple is assumed to
46+ * be an error message. Before passing it to ExcT constructor it is merged
47+ * with detail::errormsg()
48+ */
49+ template <typename ExcT, size_t ... I, typename Tuple>
50+ ExcT
51+ exception_with_errormsg_helper (index_sequence<I...>, Tuple &&args)
52+ {
53+ static_assert (std::is_rvalue_reference<decltype (args)>::value,
54+ " args should be rvalue reference!" );
55+
56+ auto msg = std::get<sizeof ...(I)>(std::move (args)) + std::string (" : " ) +
57+ detail::errormsg ();
58+ return ExcT (std::get<I>(std::move (args))..., std::move (msg));
59+ }
60+
3861/* *
3962 * Generic error message decorator for pmemobj-based exceptions.
63+ *
64+ * It accepts arbitrary number of parameters. The last parameter must be an
65+ * error message.
4066 */
41- template <class ExcT , typename MsgT >
67+ template <class ExcT , typename ... Args >
4268ExcT
43- exception_with_errormsg (const MsgT &msg )
69+ exception_with_errormsg (Args &&... args )
4470{
45- return ExcT (msg + std::string (" : " ) + detail::errormsg ());
71+ return exception_with_errormsg_helper<ExcT>(
72+ make_index_sequence<sizeof ...(Args) - 1 >{},
73+ std::forward_as_tuple (std::forward<Args>(args)...));
4674}
4775} /* namespace detail */
4876
0 commit comments