为什么 std::bind 不考虑函数 arity?
Why doesn't std::bind account for function arity?
如果我有这个简单的例子:
struct Foo
{
void bar();
void baz(int );
};
这将编译为是有道理的
Foo foo;
auto f = std::bind(&Foo::bar, &foo);
但为什么bind
会被设计成这样一种编译方式:
auto g = std::bind(&Foo::baz, &foo);
我可以呼叫f
,但我永远不能呼叫g
。为什么还要编译它?要求我必须做的理由是什么:
auto g2 = std::bind(&Foo::baz, &foo, std::placeholders::_1);
如果你想扰乱哪些参数以什么顺序传递,我可以理解使用占位符,但为什么不让默认值以正确的顺序传递所有的参数而不必指定呢?
但是,为什么要以这样一种方式设计绑定,以便编译:
auto g = std::bind(&Foo::baz, &foo);
我可以呼叫f
,但我永远不能呼叫g
。为什么还要编译它?
Boost.Bind常见问题解答说Boost.BBind通常会在";绑定时间";(即在您呼叫bind
的线路上)。然而,该标准对std::bind
没有要求,相反,它在std::bind
的Requires元素中有以下内容:
INVOKE (fd, w1, w2, ..., wN)
(20.9.2)应该是一些值w1,w2,…的有效表达式。。。,wN,其中N == sizeof...(bound_args)
。
这意味着您的代码违反了函数的前提条件,从而导致未定义的行为。标准库实现没有义务检查是否违反了先决条件,这是您的工作。库也不被禁止检查它们,所以实现拒绝它是符合要求的,就像Boost.Bind所做的那样。我会向您的库供应商提出请求,要求他们在可能的情况下诊断无效绑定表达式;实施质量";增强。(编辑:我让libstdc++的bind
这样做,从GCC 5开始。)
为什么不让默认值按正确的顺序传递所有参数而不必指定它呢?
我能想到两个原因。
首先,bind
创建的调用包装器的行为是删除与占位符不对应的参数,因此可以调用x(1, 2, 3)
并让它忽略所有参数并调用foo.bar()
。这是一个通用模式的一部分,在该模式中,您可以使用bind
包装一个N-arity函数,以创建一个具有完全不同arity的调用包装器,该调用包装器可以添加参数、删除参数、将某些参数修复为特定的绑定值等。如果绑定表达式中不使用占位符时的默认行为是转发所有参数,则x(1, 2, 3)
不可能删除所有参数。
其次,总是要求您明确表示要以何种顺序传递哪些参数更为一致。通常,只有在没有绑定参数的情况下才传递所有调用参数才有意义,否则bind
应该如何知道是在绑定参数之前还是之后传递调用参数?
例如给定
struct X {
void f(int, int) { }
} x;
auto h = bind(&X::f, &x, 1);
h(2);
对h(2)
的调用应该产生x.f(1, 2)
还是x.f(2, 1)
?由于有绑定参数时的正确行为并不明显,因此只有在没有绑定参数时才有意义(因为绑定参数不应该排在第一位还是最后一位),这是一种相当特殊的情况。改变API的一个重要特性来处理这种特殊情况将是值得怀疑的价值,特别是当它使x(1, 2, 3)
->CCD_ 23的情况不可能实现。
另一种解决方案是继续要求用户明确他们想要什么,但提供一种明确的方式来表示";只是转发一切";,这是Tomasz Kamiński在N4171中提出的,将在下周的C++委员会会议上讨论。_all
占位符解决了决定调用参数应该在绑定参数之前还是之后的问题,因为您可以明确地说您想要bind(f, arg1, arg2, std::placeholders::_all)
还是bind(f, std::placeholders::_all, arg1, arg2)
,甚至bind(f, arg1, std::placeholders::_all, arg2)
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- lambda/任意Arity的功能和以捕获为函数参数的功能
- 如何根据其ARITY(或编译时已知的其他信息)以不同的方式调用函数对象
- 为什么 std::bind 不考虑函数 arity?