Is there a workaround for implicit template argument deduction when none are provided?

  api, c++, c++14, templates

So far I don’t know if it possible at all, but I’d be glad if it was.
So the context of the question is a way of declaring an API in a way to make a function more self-explanatory. I would take for example ASIO in particular.
The way it declares asynchronous functions is kind of ambigous and relies on the comments or documentation:

/**
* @CompletionTokenT - completion token or a callable with operator()(size_t, asio::error_type)
*/
template <typename CompletionTokenT>
constexpr auto some_async_func(params, CompletionTokenT &&token);

I think it would be more convenient and consistent to have types or return arguments as a part of the funciton signature. For example:

template <typename TokenT>
constexpr auto some_async_func(params, completion<TokenT, size_t, asio::error_type> completion);

This makes requirements for a completion callable more obvious. BUT. Now it becomes very inconvenient to use, since a compiler would not be able to deduce the types.
I tried experimenting with an intermediate class with template implicit conversion operator, like

template <typename TokenT>
struct token_impl
{
   template <typename ... ArgsT>
   operator completion<TokenT, ArgsT...>();
};

But the completion_token has to be deduced first in order to make an implicit conversion, so it does not work (duh).

  • Is there some hack to circumvent implicit deduction? So the following would compile:
some_async_func(params, make_completion([](size_t, asio::error_type){});
some_async_func(params, make_completion(asio::use_future));

Another option might be to use type erasure and provide a wrapper completion<int, asio::error_type>. But that would require additional dynamic allocations.

  • What magnitude of overhead would that option have in comparison with a tempate typename CompletionTokenT version?

Here is one workaround that will enable the ease of use, but require a library provider to add a helper function:

template <template <typename, typename...> class TCompletionTokenT, typename TokenT, typename ... T>
constexpr auto some_async_func(params p, TCompletionTokenT<TokenT, T...> &&completion)
{
   return some_async_func(p, completion<TokenT, int>(std::forward<TCompletionTokenT<TokenT, T...>>(completion)));
}

Source: Windows Questions C++

LEAVE A COMMENT