While solving an online excersise I have written some basic implementation for a visit
function that works with std::any
.
The idea is to facilitate the declarative approach for handling std::any
instead of using switch
of nested if else
constructions which are very hard to maintain.
Unfortunatelly, C++ lacks reflection features to deduce a list of underlying types of std::any
object from a dispatcher
callable, so one have to provide a template list of underlying types that std::any
can hold.
Here is an example usage for solving the excercise:
int productSum(std::vector<any> array)
{
struct
{
int operator()(int i, size_t)
{
return i;
}
int operator()(const std::vector<any>& array, size_t level = 1)
{
int sum = 0;
for (const auto& a : array)
sum += level * std::get<int>(impl::visit<int,
std::vector<any>>(*this, a, level + 1));
return sum;
}
} dispatcher{};
return dispatcher(array);
}
And the implementation itself:
#include <utility>
#include <variant>
#include <type_traits>
namespace impl
{
template <typename T, typename... Ts>
struct unique{ using type = T; };
template <typename... Ts, typename U, typename... Us, template <typename...> class TTupleT>
struct unique<TTupleT<Ts...>, U, Us...> :
std::conditional_t<std::disjunction_v<std::is_same<U, Ts>...>,
unique<TTupleT<Ts...>, Us...>,
unique<TTupleT<Ts..., U>, Us...>>
{};
template <typename ... T>
using unique_variant = typename unique<std::variant<>, T...>::type;
// TODO: remove duplicate return values from variant
template <typename ... DispatchT, typename CallableT, typename ... ArgsT>
auto visit(CallableT &&callable, const std::any& any, ArgsT &&... args)
{
using retval_t = unique_variant<decltype(std::declval<CallableT>()(std::declval<DispatchT>(),
std::declval<ArgsT>()...))...>;
retval_t ret{};
// typeid can't be used within a fold expression
(void)std::initializer_list<int>{(any.type() == typeid(DispatchT) &&
(ret = std::forward<CallableT>(callable)(
std::any_cast<DispatchT>(any),
std::forward<ArgsT>(args)...
),
false),0)...};
return ret;
}
}
I know that most certainly there are problems with type qualifiers, so I would appreciate any advice.