我实现了一个 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&){}
)lambda 时,它会因用户不友好的编译时错误而爆炸。有没有办法检测到这一点并给予好评static_assert()
?如果它也可以与函数模板一起使用,而不仅仅是 lambdas,那就太好了。
请注意,我不知道 lambda 可以做什么,所以我不能用 Dummy 类型做一些聪明的事情,因为 lambda 可能会调用类型上的任意函数。换句话说,我不能尝试在 2std::void_t
次测试中调用 lambdaint
并且std::string
如果它有效,则假设它是通用的,因为他们可能会尝试.BlaLol()
调用int
and string
。