如何使这些std ::函数参数明确? [英] How to make these std::function parameters unambiguous?

查看:114
本文介绍了如何使这些std ::函数参数明确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

传递lambda时,以下函数重载是不明确的。我发现 std :: function 可以从大多数可调用类型构造< a>,即使他们的签名不匹配。所以编译器不能告诉使用哪个函数。

The following function overloads are ambiguous when passing a lambda. I found out that std::function can be constructed from most callable types, even if their signature does not match. So the compiler can't tell which function to use.

template <typename T> void each(std::function<void(T)> iterator);
template <typename T> void each(std::function<void(T, id)> iterator);
template <typename T> void each(std::function<void(T&)> iterator);
template <typename T> void each(std::function<void(T&, id)> iterator);

这里有一些类似的问题,但是没有一个可以解决我的问题。如何在不改变用法的情况下解决模糊?更多,当时我必须明确提及模板类型。

There are some similar questions out here, but none of them could solve my problem. How can I resolve the ambiguity without changing the usage? Morever, at the time I have to explicitly mention the template type. Is there a way around this?

推荐答案

其中一半是 LWG问题2132 ,删除 std :: function 的构造函数,除非参数实际上是可调用的参数类型指定。这需要表达式SFINAE支持来实现,VC ++没有。

One half of this is LWG issue 2132, removing std::function's constructor from overload resolution unless the argument is actually callable for the argument types specified. This requires expression SFINAE support to implement, which VC++ doesn't have.

问题的另一半是重载解析:

The other half of the issue is overload resolution:

#include<functional>
#include<iostream>
struct id {};
template <typename T> void each(std::function<void(T)> ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
template <typename T> void each(std::function<void(T, id)> ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
template <typename T> void each(std::function<void(T&)> ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
template <typename T> void each(std::function<void(T&, id)> ){ std::cout << __PRETTY_FUNCTION__ << std::endl; }
int main() {
    each<int>([](int, id){});
}

使用实现LWG2132的库,这段代码打印,可能会令人惊讶:

With a library that implements LWG2132, this code prints, perhaps surprisingly:

void each(std::function<void(T&, id)>) [with T = int]


b $ b

为什么?首先,可以从 [](int,id){...构造一个 std :: function< void(T& id)> } 。毕竟,后者可以用类型 int 的左值调用。

Why? First, it is possible to construct a std::function<void(T&, id)> from [](int, id){}. After all, the latter can be called with a lvalue of type int just fine.

Second,in

Second, in

template <typename T> void each(std::function<void(T, id)>);
template <typename T> void each(std::function<void(T&, id)>);

第二个是比第一个更专门的功能模板的部分排序规则,通过重载解析。

The second is more specialized than the first by the partial ordering rules for function templates, so it's always chosen by overload resolution.

一个可能的解决方案是通过操作lambda的 operator()

A possible solution is to extract the signature by manipulating the type of the lambda's operator ():

template<class T>
struct mem_fn_type;
template<class R, class C, class... T>
struct mem_fn_type<R(C::*)(T...)> {
    using type = std::function<R(T...)>;
};
template<class R, class C, class... T>
struct mem_fn_type<R(C::*)(T...) const> {
    using type = std::function<R(T...)>;
};

// optional extra cv-qualifier and ref-qualifier combos omitted
// since they will never be used with lambdas    

// Detects if a class is a specialization of std::function
template<class T>
struct is_std_function_specialization : std::false_type {};

template<class T>
struct is_std_function_specialization<std::function<T>> : std::true_type{};

// Constrained to not accept cases where T is a specialization of std::function,
// to prevent infinite recursion when a lambda with the wrong signature is passed
template<class T>
typename std::enable_if<!is_std_function_specialization<T>::value>::type each(T func) {
    typename mem_fn_type<decltype(&T::operator())>::type f = func;
    each(f);
}

这不适用于通用lambdas(其 operator()是一个模板)或任意函数对象(可能有任意多个 operator()重载)。

This won't work for generic lambdas (whose operator() is a template) or for arbitrary function objects (which may have arbitrarily many operator() overloads).

这篇关于如何使这些std ::函数参数明确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆