Опираясь на ответ @ Caleth, это позволяет использовать любой вариант без дублирования списка параметров.
#include <vector>
#include <variant>
#include <type_traits>
//Replace with more appropriate name
template<typename Variant, typename Lambda>
struct X_impl;
template<typename...Ts, typename Lambda>
struct X_impl<std::variant<Ts...>, Lambda>{
using type = std::variant<std::invoke_result_t<Lambda,Ts>...>;
};
template<typename...Ts, typename Lambda>
struct X_impl<const std::variant<Ts...>, Lambda>{
using type = std::variant<std::invoke_result_t<Lambda,const Ts>...>;
};
template<typename Variant, typename Lambda>
using X = typename X_impl<std::remove_reference_t<Variant>, Lambda>::type;
template<typename Variant, typename Lambda>
auto visit(Variant&& variant, Lambda&& lambda){
auto wrapped_lambda = [&lambda](auto&& arg) -> X<Variant,Lambda>{
using T = decltype(arg);
return std::forward<Lambda>(lambda)(std::forward<T>(arg));
};
return std::visit(wrapped_lambda, std::forward<Variant>(variant));
}
int main()
{
std::variant<std::vector<int>,const std::vector<double> > vr = std::vector<int>(5, 5);
const std::variant<std::vector<int>,const std::vector<double> > c_vr = std::vector<int>(5, 5);
auto& ref_vr = vr;
auto& ref_c_vr = c_vr;
auto visit_fnc = [](auto&& a){return a.begin();};
visit(vr, visit_fnc);
visit(c_vr, visit_fnc);
visit(ref_vr, visit_fnc);
visit(ref_c_vr, visit_fnc);
}
EDIT:
О, похоже, @Caleth также добавил общее решение.