C++11 个带提升的占位符
C++11 placeholders with boost
这段代码...
int main()
{
using namespace std::placeholders;
ClassA a;
ClassB b, b2;
a.SigA.connect( std::bind(&ClassB::PrintFoo, &b) );
a.SigB.connect( std::bind(&ClassB::PrintInt, b, _1));
a.SigB.connect( std::bind(&ClassB::PrintInt, &b2, _1));
a.SigA();
a.SigB(4);
}
给出编译错误,"错误:对'_1'的引用不明确"
它可以通过完全限定占位符来修复......
int main()
{
// using namespace std::placeholders;
ClassA a;
ClassB b, b2;
a.SigA.connect( std::bind(&ClassB::PrintFoo, &b) );
a.SigB.connect( std::bind(&ClassB::PrintInt, b, std::placeholders::_1));
a.SigB.connect( std::bind(&ClassB::PrintInt, &b2, std::placeholders::_1));
a.SigA();
a.SigB(4);
}
。但是为什么第一个代码片段不起作用呢?
编辑
只是为了防止任何歧义,我正在使用 Clang 和 Boost 1.5 --stdlib=libc++ -std=c++0x
2 进行编译,整个代码块都是这个......
#include <boost/signals2.hpp>
#include <iostream>
struct ClassA
{
boost::signals2::signal<void ()> SigA;
boost::signals2::signal<void (int)> SigB;
};
struct ClassB
{
void PrintFoo() { std::cout << "Foo" << std::endl; }
void PrintInt(int i) { std::cout << "Bar: " << i << std::endl; }
};
int main()
{
// using namespace std::placeholders;
ClassA a;
ClassB b, b2;
a.SigA.connect( std::bind(&ClassB::PrintFoo, &b) );
a.SigB.connect( std::bind(&ClassB::PrintInt, b, std::placeholders::_1));
a.SigB.connect( std::bind(&ClassB::PrintInt, &b2, std::placeholders::_1));
a.SigA();
a.SigB(4);
}
让我们看看包含是如何工作的:
#include <boost/signals2.hpp>
包括#include <boost/signals2/signal.hpp>
其中包括#include <boost/signals2/slot.hpp>
包括#include <boost/bind.hpp>
包括#include <boost/bind/bind.hpp>
包括 include <boost/bind/placeholders.hpp>
,它在全局命名空间中使用 static boost::arg<1> _1;
*,因此歧义。
*:从技术上讲,_1
位于未命名的命名空间中,但由于 using 指令而可见。
一种解决方法是在文件顶部定义以下内容,以便不包含<boost/bind/placeholders.hpp>
:
#define BOOST_BIND_NO_PLACEHOLDERS
C++看到两个名为 _1
的全局标识符。它不知道你的意思是std::placeholders::_1
而不是 Boost 的_1
.这就是标准库将它们放在嵌套命名空间中的原因之一:以防止此类意外冲突。
如果需要它们更短,只需创建一个简单的命名空间别名:
namespace ph = std::placeholders
然后就ph::_1
GCC 提供有关您的错误的以下信息:
.../include/c++/4.7.0/functional:864:34:
error: candidates are: const std::_Placeholder<1> std::placeholders::_1
.../boost/1.49.0/boost/bind/placeholders.hpp:55:15:
error: boost::arg<1> {anonymous}::_1
问题的提示可以在第二个错误中找到:boost::arg<1> {anonymous}::_1
原因是 boost 占位符位于全局命名空间中的匿名命名空间中。
namespace
{
boost::arg<1> _1;
// etc...
} // unnamed namespace
由于 boost 占位符位于匿名命名空间中,并且你要将std::placeholders
导入全局命名空间,因此它们现在在全局范围内都可用。
因此,编译器无法知道您指的是哪个符号。
正如 Nicol 建议的那样,使用命名空间别名来创建速记前缀来std::placeholders::_1
以减少类型。
既然你正在使用std::bind
我想你有一些 C++11 支持。也考虑这个版本(即更喜欢 lambda 而不是 std::bind
)
int main()
{
ClassA a;
ClassB b, b2;
a.SigA.connect( [&](){ b.PrintFoo(); } );
a.SigB.connect( [&](int i){ b.PrintInt(i); } );
a.SigB.connect( [&](int i){ b2.PrintInt(i); } );
a.SigA();
a.SigB(4);
}
使用局部变量在作用域内解决此问题的另一种解决方法:
{
auto& _1 = std::placeholders::_1;
auto f = std::bind(&Foo::bar, b, _1);
...
}
- 将模板与类模板扣除占位符参数匹配
- C++初始化 std::function 时如何将占位符绑定到引用/引用参数?
- Tensorflow C++ 占位符初始化
- std::bind 不会接受 bind 占位符的 std::cref - 为什么?
- qt 中的占位符
- 我可以在 c++ 中使用占位符作为数组的索引吗?
- 为什么协程不允许使用占位符返回类型?
- TensorFlow类占位符以及其他定义输入张量的方法
- QtLineEdit 占位符:如何让用户在插入模式下将字符 1 替换为 1
- 非类型模板参数中的占位符类型是否涉及作为模板参数传递的函数的重载解析?
- 是否可以使用自动占位符来推断非类型模板参数中的函数结果
- 如何使用 msgfmt 验证格式字符串中的位置表示法占位符
- 无法推断出占位符的概念
- 编译器错误boost :: asio ::占位符:: boost v1.69的错误
- std::绑定可变参数模板、绑定参数和占位符
- 尾随返回类型中的占位符类型的用途是什么
- 如何在折叠过程中获取成员类型的提升::mpl 占位符
- C++11 个带提升的占位符
- 是否可以在 c++11 中扩展 std::tie 以接受占位符?
- 使用c++11占位符作为lambda