参数依赖查找在这里看起来如何*?

时间:2015-12-24 07:54:03

标签: c++ boost c++14 argument-dependent-lookup

在VS2015中(但不是在多个平台上使用各种其他编译器,包括VS10),我得到了

Charlie\Gamma.cpp(224): error C2668: 'boost::make_shared': ambiguous call to overloaded function
  E:\C++Libs\boost_1_60_0\boost/smart_ptr/make_shared_object.hpp(246): note: could be 'boost::shared_ptr<T> boost::make_shared<Able::Bravo::Charlie::Dog,Able::Bravo::Charlie::Egg&,const uint32_t&,const Frank&>(Able::Bravo::Charlie::Egg &,const uint32_t &,const Frank &)' [found using argument-dependent lookup]
          with
          [
              T=Able::Bravo::Charlie::Dog
          ] (compiling source file Charlie\Gamma.cpp)
  D:\@Prog-Charon\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\memory(968): note: or       'std::shared_ptr<Able::Bravo::Charlie::Dog> std::make_shared<Able::Bravo::Charlie::Dog,Able::Bravo::Charlie::Egg&,const uint32_t&,const Frank&>(Able::Bravo::Charlie::Egg &,const uint32_t &,const Frank &)' (compiling source file Charlie\Gamma.cpp)
  Charlie\Gamma.cpp(224): note: while trying to match the argument list '(Able::Bravo::Charlie::Egg, const uint32_t, const Frank)'

(我的封闭源名称已经过消毒,Boost和标准名称保持不变)

代码是:

namespace Able {
namespace Bravo {
namespace Charlie {


using std::string;
using std::tr1::shared_ptr;
using std::tr1::make_shared;

⋮  // then later in the file

shared_ptr<Dog> Gamma::knockout (const Hotel& target)
{
   Egg softboiled (target.ID);
   softboiled.sequence ^= 0x40000000;
   return make_shared<Dog>(softboiled, target.kin, Frank::myself());
}

使用make_sharedstd::tr1::make_shared通过using声明进入范围,这是什么意思。该错误表明它正在解析为std::make_shared,我希望tr1只是一堆typedef以实现向后兼容。

但它也报告通过依赖于参数的查找来查找boost::make_shared。但争论是

Able::Bravo::Charlie::Egg &,
const uint32_t &,
const Frank &

其中没有一个位于boost命名空间中。

那么为什么通过参数依赖查找找到boost::make_shared

,可能是因为Frank来自boost::totally_ordered1的{​​em>私下(Egg来自boost::totally_ordered )?这是查找规则的变化,编译器的一个中的修复或错误,还是类似的东西?

如果这是正确的,那么任何使用boost的混合类型都会引起各种歧义,因为旧的增强内容与现在标准函数的名称或一般的通用名称相匹配。这些私有基类最终污染了我的类的命名空间,甚至没有在公共界面中显而易见,它与boost有关!这可能是对的。

更新:这与Boost 1.60相同,但与Boost 1.59无关。所以忽略了我的结论,它因编译器/平台的不同而有所不同:它使用较旧版本的Boost在各种平台上工作。

我转向最新版本的Boost作为解决Boost发生的编译时问题的第一步,它似乎引入了另一个。

Boost的operators.hpp在命名空间struct totally_ordered2中定义了模板boost等,而不是在Boost 1.59版中更加花哨。

1 个答案:

答案 0 :(得分:4)

看起来确实如此,因为就像你说的那样Frank来自boost::totally_ordered1

§3.4.2[C ++ 14标准[n4296]的[basic.lookup.argdep]指定了所考虑的命名空间和类的集合。这是§3.4.2/ 2:

  

对于函数调用中的每个参数类型T,都有一组零个或多个关联的命名空间以及一组零个或多个要考虑的关联类。命名空间和类的集合完全由函数参数的类型(以及任何模板模板参数的命名空间)决定。用于指定类型的Typedef名称和 using-declarations 对此集合没有贡献。命名空间和类的集合按以下方式确定:

和§3.4.2/ 2.2关注类类型:

  

如果T是类类型(包括联合),则其关联的类是:类本身;它所属的成员,如果有的话; 及其直接和间接基类其关联的命名空间是其关联类的最内部封闭命名空间。此外,如果T是类模板特化,则其关联的名称空间和类还包括:与模板类型参数(模板模板参数除外)提供的模板参数类型相关联的名称空间和类;任何模板模板参数都是成员的名称空间;以及用作模板模板参数的任何成员模板的类都是成员。 [注意:非类型模板参数不会对相关命名空间的集合产生影响。 - 结束记录]

编辑:刚看到你的更新,不知道在相同的编译器,标志和C ++版本下,在1.59中工作的原因是什么,而不是1.60。