C++ C++;11个带boost的占位符
此代码C++ C++;11个带boost的占位符,c++,c++11,boost,C++,C++11,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(&
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.52编译--stdlib=libc++-std=c++0x
,整个代码块如下所示
#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);
}
#包括
#包括
结构类A
{
升压::信号2::信号SigA;
升压::信号2::信号SigB;
};
结构类B
{
void PrintFoo(){std::coutC++看到两个名为\u 1
的全局标识符。它不知道您指的是std::placeholder::\u 1
而不是Boost的\u 1
。这就是标准库将它们放在嵌套命名空间中的原因之一:防止像这样的意外冲突
如果需要更短,只需创建一个简单的命名空间别名:
namespace ph = std::placeholders
然后就是ph::_1
让我们看看include是如何工作的:
#包括
包括
#包括
其中包括#include
其中包括#include
其中包括#include
其中包括include
,它在全局名称空间中使用静态boost::arg\u 1;
*,因此存在歧义
*:从技术上讲,\u 1
位于未命名的命名空间中,但由于using指令,它可见
一种解决方法是在文件顶部定义以下内容,以便不包括
:
#define BOOST_BIND_NO_PLACEHOLDERS
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
../include/c++/4.7.0/functional:864:34:\
错误:候选项为:const std::_占位符std::占位符::_1
…/boost/1.49.0/boost/bind/placeholders.hpp:55:15:\
错误:boost::arg{anonymous}::\u 1
问题的提示可以在第二个错误中找到:boost::arg{anonymous}::_1
原因是boost占位符位于全局命名空间中的匿名命名空间中
namespace
{
boost::arg<1> _1;
// etc...
} // unnamed namespace
名称空间
{
boost::arg_1;
//等等。。。
}//未命名的命名空间
由于boost占位符位于匿名名称空间中,并且您正在将std::placeholder
导入全局名称空间,因此它们现在都在全局范围内可用
因此,编译器无法知道所引用的符号
如Nicol建议的,使用命名空间别名来创建一个速记前缀,以<代码> STD::占位符::“1”/“代码”以减少键入。
< P>因为您使用的是通过使用局部变量在范围内解决此问题的另一种解决方法:
{
auto& _1 = std::placeholders::_1;
auto f = std::bind(&Foo::bar, b, _1);
...
}
你在用什么…编译器?编辑:没关系,
clang
使用\uuu1
作为它奇怪的名称空间。如果范围中还有其他称为1的东西,那么你会得到这个错误。有点太晚了!很好。Bind很难看!+1在所有伟大的答案中,这一个最直接地回答了这个问题,所以+1/accept我很想知道hy Boost这样污染了全局名称空间?为什么不让用户使用名称空间Boost::占位符;而不管他们想在哪里?
{
auto& _1 = std::placeholders::_1;
auto f = std::bind(&Foo::bar, b, _1);
...
}