NoS*_*tAl 10 c++ template-meta-programming variadic-templates generic-lambda c++17
我实现了一个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
}
Run Code Online (Sandbox Code Playgroud)
这可行,但是当用户传递通用(例如[](auto&){})lambda 时,会因用户不友好的编译时错误而爆炸。有没有一种方法可以检测到这个并给出好static_assert()结果?如果它也可以与函数模板一起使用,而不仅仅是与lambdas一起使用,那也将很好。
请注意,我不知道lambda可能做什么,因此我无法对Dummy类型做一些聪明的事情,因为lambda可能会在类型上调用任意函数。换句话说,我不能尝试调用拉姆达2周std::void_t的测试上int,并std::string和它是否工作假定它是通用的,因为他们可能会尝试打电话.BlaLol()的int和string。
max*_*x66 11
有没有一种方法可以检测到这一点,并为此提供很好的static_assert?
我想您可以在operator()类型上使用SFINAE 。
跟随一个例子
#include <type_traits>
template <typename T>
constexpr auto foo (T const &)
-> decltype( &T::operator(), bool{} )
{ return true; }
constexpr bool foo (...)
{ return false; }
int main()
{
auto l1 = [](int){ return 0; };
auto l2 = [](auto){ return 0; };
static_assert( foo(l1), "!" );
static_assert( ! foo(l2), "!" );
}
Run Code Online (Sandbox Code Playgroud)
如果您想通过使用它bool,可以代替std::true_type(从foo()第一个版本)或std::false_type(从第二个版本)返回decltype()。
如果它也可以与函数模板一起使用,而不仅仅是与lambdas一起使用,那也将很好。
我认为不可能这么简单:lambda(也是泛型lambda)是对象;模板函数不是对象,而是一组对象。您可以将一个对象传递给一个函数,而不是一组对象。
但是,前面的解决方案也应适用于带有operator()s的类/结构:如果有单个非模板,operator()则应1从foo(); 获得;否则(不operator()超过一个operator(),模板operator())foo()应返回0。
| 归档时间: |
|
| 查看次数: |
867 次 |
| 最近记录: |