Я реализовал функцию Visit (для варианта), которая проверяет, соответствует ли текущий активный тип в варианте сигнатуре функции (точнее, первому аргументу). На основании этого милого ответа .
Например
#include <variant>
#include <string>
#include <iostream>
template<typename Ret, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(*) (Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...));
template<typename Ret, typename F, typename Arg, typename... Rest>
Arg first_argument_helper(Ret(F::*) (Arg, Rest...) const);
template <typename F>
decltype(first_argument_helper(&F::operator())) first_argument_helper(F);
template <typename T>
using first_argument = decltype(first_argument_helper(std::declval<T>()));
std::variant<int, std::string> data="abc";
template <typename V>
void Visit(V v){
using Arg1 = typename std::remove_const_t<std::remove_reference_t<first_argument<V>>>;//... TMP magic to get 1st argument of visitor + remove cvr, see Q 43526647
if (! std::holds_alternative<Arg1>(data)) {
std::cerr<< "alternative mismatch\n";
return;
}
v(std::get<Arg1>(data));
}
int main(){
Visit([](const int& i){std::cout << i << "\n"; });
Visit([](const std::string& s){std::cout << s << "\n"; });
// Visit([](auto& x){}); ugly kabooom
}
Это работает, но взрывается, когда пользователь недружелюбно компилирует ошибку времени компиляции, когда пользователь передает стандартную (например, [](auto&){}
) лямбду. Есть ли способ обнаружить это и дать хороший static_assert()
об этом?
Было бы также неплохо, если бы он работал с шаблонами функций, а не только с лямбдами.
Обратите внимание, что я не знаю, что делают возможные лямбды, поэтому я не могу делать некоторые умные вещи с типами Dummy, так как лямбды могут вызывать произвольные функции для типов.
Другими словами, я не могу попытаться вызвать лямбду в 2 std::void_t
тестах на int
и std::string
, и если это работает, предположим, что это универсально, потому что они могут попытаться вызвать .BlaLol()
на int
и string
.