@@ -122,51 +122,6 @@ class pg_result_t
122122 std::unique_ptr<PGresult, pg_result_deleter_t > m_result;
123123};
124124
125- // Do not use anonymous namespace in header file
126- // https://wiki.sei.cmu.edu/confluence/display/cplusplus/DCL59-CPP.+Do+not+define+an+unnamed+namespace+in+a+header+file
127- namespace detail {
128-
129- /* *
130- * Helper for pg_conn_t::exec_prepared() function. All parameters to
131- * that function are given to the exec_arg::to_str function which will
132- * pass through string-like parameters and convert other parameters to
133- * strings.
134- */
135- template <typename T>
136- struct exec_arg
137- {
138- constexpr static std::size_t const buffers_needed = 1 ;
139- static char const *to_str (std::vector<std::string> *data, T param)
140- {
141- return data->emplace_back (fmt::to_string (std::forward<T>(param)))
142- .c_str ();
143- }
144- };
145-
146- template <>
147- struct exec_arg <char const *>
148- {
149- constexpr static std::size_t const buffers_needed = 0 ;
150- static char const *to_str (std::vector<std::string> * /* data*/ ,
151- char const *param) noexcept
152- {
153- return param;
154- }
155- };
156-
157- template <>
158- struct exec_arg <std::string const &>
159- {
160- constexpr static std::size_t const buffers_needed = 0 ;
161- static char const *to_str (std::vector<std::string> * /* data*/ ,
162- std::string const ¶m) noexcept
163- {
164- return param.c_str ();
165- }
166- };
167-
168- } // namespace detail
169-
170125/* *
171126 * PostgreSQL connection.
172127 *
@@ -258,6 +213,39 @@ class pg_conn_t
258213 int *param_lengths, int *param_formats,
259214 int result_format) const ;
260215
216+ /* *
217+ * Helper for pg_conn_t::exec_prepared_with_result_format() function. Used
218+ * to find out how many buffers we need. Must always be in sync with the
219+ * to_str() function below.
220+ */
221+ template <typename T>
222+ static constexpr std::size_t buffers_needed () noexcept
223+ {
224+ if constexpr (std::is_same_v<T, char const *>) {
225+ return 0 ;
226+ } else if constexpr (std::is_same_v<T, std::string>) {
227+ return 0 ;
228+ }
229+ return 1 ;
230+ }
231+
232+ /* *
233+ * Helper for pg_conn_t::exec_prepared_with_result_format() function. All
234+ * parameters to that function are given to the to_str() function which
235+ * will pass through string-like parameters and convert other parameters to
236+ * strings.
237+ */
238+ template <typename T>
239+ static char const *to_str (std::vector<std::string> *data, T const ¶m)
240+ {
241+ if constexpr (std::is_same_v<T, char const *>) {
242+ return param;
243+ } else if constexpr (std::is_same_v<T, std::string>) {
244+ return param.c_str ();
245+ }
246+ return data->emplace_back (fmt::to_string (param)).c_str ();
247+ }
248+
261249 /* *
262250 * Run the named prepared SQL statement and return the results.
263251 *
@@ -279,16 +267,16 @@ class pg_conn_t
279267 // so that pointers into the strings in that vector remain valid
280268 // after new parameters have been added.
281269 constexpr auto const total_buffers_needed =
282- (0 + ... + detail::exec_arg <TArgs>::buffers_needed );
270+ (0 + ... + buffers_needed<std:: decay_t <TArgs>>() );
283271 std::vector<std::string> exec_params;
284272 exec_params.reserve (total_buffers_needed);
285273
286274 // This array holds the pointers to all parameter strings, either
287275 // to the original string parameters or to the recently converted
288276 // in the exec_params vector.
289277 std::array<char const *, sizeof ...(params)> param_ptrs = {
290- detail::exec_arg <TArgs>:: to_str (&exec_params,
291- std::forward<TArgs>(params))...};
278+ to_str<std:: decay_t <TArgs>> (&exec_params,
279+ std::forward<TArgs>(params))...};
292280
293281 return exec_prepared_internal (stmt, sizeof ...(params),
294282 param_ptrs.data (), nullptr , nullptr ,
0 commit comments