- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
鉴于以下代码,歧义背后的原因是什么?我可以绕过它还是必须保留(烦人的)显式转换?
#include <functional>
using namespace std;
int a(const function<int ()>& f)
{
return f();
}
int a(const function<int (int)>& f)
{
return f(0);
}
int x() { return 22; }
int y(int) { return 44; }
int main()
{
a(x); // Call is ambiguous.
a(y); // Call is ambiguous.
a((function<int ()>)x); // Works.
a((function<int (int)>)y); // Works.
return 0;
}
有趣的是,如果我注释掉 a()
function<int ()>
的函数参数和调用a(x)
在我的主要,由于 x
之间的类型不匹配,编译正确失败和论点 function<int (int)>
唯一的a()
可用的功能。如果在那种情况下编译器失败,为什么在两个 a()
时会有任何歧义?函数存在吗?
我已尝试使用 VS2010 和 g++ v. 4.5。两者都给了我完全相同的歧义。
最佳答案
问题在于 function<int()>
和 function<int(int)>
可以从相同的函数构造。这就是 std::function
的构造函数声明VS2010 中的样子:
template<class _Fx>
function(_Fx _Func, typename _Not_integral<!_Is_integral<_Fx>::value, int>::_Type = 0);
忽略 SFINAE 部分,它几乎可以用任何东西构建。
std::/boost::function
采用一种称为类型删除的技术,允许传入任意对象/函数,只要它们在调用时满足签名即可。这样做的一个缺点是,当提供一个不能像签名希望的那样调用的对象时,而不是在构造函数中,您在实现的最深部分(调用保存的函数的地方)会遇到错误。
这个问题可以用这个小类来说明:
template<class Signature>
class myfunc{
public:
template<class Func>
myfunc(Func a_func){
// ...
}
};
现在,当编译器为重载集搜索有效函数时,如果不存在完美拟合函数,它会尝试转换参数。转换可以通过函数参数的构造函数发生,也可以通过给函数的参数的转换运算符发生。在我们的例子中,是前者。
编译器尝试 a
的第一个重载.为了使其可行,它需要进行转换。转换 int(*)()
到 myfunc<int()>
, 它尝试 myfunc
的构造函数.作为一个接受任何东西的模板,转换自然会成功。
现在它尝试与第二个重载相同。构造函数仍然是相同的,并且仍然接受给它的任何东西,转换也有效。
在重载集中留下了 2 个函数,编译器是一只可悲的 Pandas ,不知道该做什么,所以它只是说这个调用是模棱两可的。
所以最后,Signature
模板的一部分在进行声明/定义时确实属于该类型,但在您要构造对象时则不属于。
编辑:
我全神贯注地回答标题问题,我完全忘记了你的第二个问题。 :(
Can I circumvent it or will I have to keep the (annoying) explicit casts?
Afaik,您有 3 个选项。
制作 function
适当类型的对象并传递它
function<int()> fx = x;
function<int(int)> fy = y;
a(fx);
a(fy);
在函数中隐藏繁琐的转换并使用 TMP 获得正确的签名
TMP(模板元编程)版本非常冗长且带有样板代码,但它对客户端隐藏了转换。可以找到示例版本 here ,它依赖于 get_signature
部分专门用于函数指针类型的元函数(并提供了一个很好的例子,模式匹配如何在 C++ 中工作):
template<class F>
struct get_signature;
template<class R>
struct get_signature<R(*)()>{
typedef R type();
};
template<class R, class A1>
struct get_signature<R(*)(A1)>{
typedef R type(A1);
};
当然,这需要针对您想要支持的参数数量进行扩展,但只需完成一次,然后将其隐藏在 "get_signature.h"
中。标题。 :)
我考虑过但立即放弃的另一个选项是 SFINAE,它会引入比 TMP 版本更多的样板代码。
所以,是的,这就是我所知道的选项。希望其中一个对你有用。 :)
关于c++ - std::function 的模板参数(签名)不是其类型的一部分吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5931214/
我得到了这个printHashKey函数,它运行良好。 fun printHashKey() { try { val info : PackageInfo = packageM
如何使用正确的签名 key 为我的 Android 应用包签名? 最佳答案 我尝试在此处和 this question 中使用多个答案, 但不知何故我收到了这个错误,因为我的 android/app/
我的 gradle 文件中有这个: android { signingConfigs { mySigningConfig { keyAlias 'the
请至少选择一个签名版本以在 Android Studio 2.3 中使用 现在在 Android Studio 中生成一个签名的 APK 时,它显示了两个选项(复选框),即 1. V1(Jar 签名)
我想表示一些标量值(例如整数或字符串)通过它的实际值或一些 NA 值,然后存储它们在集合中(例如列表)。目的是处理缺失值。 为此,我实现了一个签名 module type Scalar = sig
为什么这不完全有效? sum :: (Num a, Num b) => a -> b -> c sum a b = a + b 当然,错误消息与签名有关,但我仍然不明白原因。 Couldn't mat
谢谢帮助,我的问题是关于从下面的代码中收到的 ax 值? mov al,22h mov cl,0fdh imul cl 真机结果:ff9a 我的预期:00:9a(通过二进制相乘) 第一个数字是 22h
我有一个注释: import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.
我从对物体的思考中得出了一个术语。当我们扩展一个类时,扩展类将具有与父类相同的签名,因此术语 IS-A 来自...示例 class Foo{ } class Foo2 extends Foo{ } c
我需要在有符号整数和它们作为字节序列的内部表示之间进行转换。在 C 中,我使用的函数如下: unsigned char hibyte(unsigned short i) {return i>>8;}
我正在尝试使用给定的 RSA 参数对一些数据进行签名。 我给出了模数、指数、D、DP、DQ、P、Q 和 InverseQ。什么库或方法最容易使用来计算此签名。在 C# 中,一旦您提供参数,它们就会有一
这些签名之间有什么区别? T * f(T & identifier); T & f(T & identifier); T f(T & identifier); void f(T * identifie
这个问题在这里已经有了答案: 关闭 11 年前。 Possible Duplicate: Where and why do I have to put the “template” and “typ
我有一个签名,我需要在签名旁边添加图片。但我不确定 css 的确切程度和内容。目前它显示在文字下方,我应该把图片放在哪里?在相同的 tr 或 td 中?
查看 LinkedHashMap 的 JDK 源代码,我注意到这个类被声明为: public class LinkedHashMap extends HashMap im
背景:我继承了一个基于 linux 的嵌入式系统,其中包含一个 SMTP 代理和一些我不得不忍受的古怪限制。它位于 SMTP 客户端和服务器之间。当 SMTP 客户端连接时,代理会打开与服务器的连接,
这是 C++17 形式的规则 ([basic.lval]/8),但它在其他标准中看起来很相似(在 C++98 中是“lvalue”而不是“glvalue”): 8 If a program attem
我有一个注释: import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.
我即将开展一个项目,希望使用电子签名板使用 C# 捕获客户的签名、在设备上显示文本等。 现在,在我开始做进一步的研究之前,我想向你们征求一些意见/建议,我应该使用哪些设备.. 我现在的要求非常笼统:我
呢喃自己在心中开始扩张地盘,仿佛制式地广播了三次。 漾起的涟绮,用谈不上精腻的手段。 拒绝天亮,却又贪恋着贪恋多情的日光。 川流不息的画面是他们,而我的落幕停在右脚,它渴望着下台,而我只剩自言
我是一名优秀的程序员,十分优秀!