C ++命名空间歧义

时间:2011-02-21 08:25:00

标签: c++

我有::tensor::contract::tensor::detail::contract

#include "tensor/detail/contract.hpp"

namespace tensor {


    template<typename Alpha, class A, class B, typename Beta, class C>
    void contract(Alpha alpha, A a, B b, Beta beta, C c) {
        detail::contract(alpha, a, b, beta, c);
    }

    template<class A, class B, typename U = int>
    struct contract_expression :
        expression<contract_expression<A,B,U> >
    {
        template<typename T, class C>
        void evaluate(T alpha, T beta, expression<C> &c) const {
            contract(alpha*alpha_, a, b, beta, c); // ambiguity here
        };
    };

为什么我会在contract_expression::evaluate中出现歧义?我相当确定没有流浪using指令。

错误:

 ../../src/tensor/contract.hpp:12: note: candidates are: void tensor::contract(Alpha, A, B, Beta, C) [with Alpha = int, A = tensor::tensor_view<boost::detail::multi_array::multi_array_view<d\
ouble, 2u>, boost::fusion::map<tensor::index<98, tensor::detail::index_range>, tensor::index<97, tensor::detail::index_range>, boost::fusion::void_, boost::fusion::void_, boost::fusion::voi\
d_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, B = tensor::tensor_view<boost::detail::multi_array::multi_array_view<dou\
ble, 3ul>, boost::fusion::map<tensor::index<97, tensor::detail::index_range>, tensor::index<99, tensor::detail::index_range>, tensor::index<100, tensor::detail::index_range>, boost::fusion:\
:void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, Beta = int, C = tensor::tensor_view<boost::det\
ail::multi_array::multi_array_view<double, 3ul>, boost::fusion::map<tensor::index<98, tensor::detail::index_range>, tensor::index<99, tensor::detail::index_range>, tensor::index<100, tensor\
::detail::index_range>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >]
../../src/tensor/detail/contract.hpp:109: note:                 void tensor::detail::contract(Alpha, A, B, Beta, C) [with Alpha = int, A = tensor::tensor_view<boost::detail::multi_array::mu\
lti_array_view<double, 2u>, boost::fusion::map<tensor::index<98, tensor::detail::index_range>, tensor::index<97, tensor::detail::index_range>, boost::fusion::void_, boost::fusion::void_, bo\
ost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, B = tensor::tensor_view<boost::detail::multi_array::mult\
i_array_view<double, 3ul>, boost::fusion::map<tensor::index<97, tensor::detail::index_range>, tensor::index<99, tensor::detail::index_range>, tensor::index<100, tensor::detail::index_range>\
, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_> >, Beta = int, C = tensor::tensor\
_view<boost::detail::multi_array::multi_array_view<double, 3ul>, boost::fusion::map<tensor::index<98, tensor::detail::index_range>, tensor::index<99, tensor::detail::index_range>, tensor::i\
ndex<100, tensor::detail::index_range>, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::void_, boost::fusion::vo\
id_> >]

2 个答案:

答案 0 :(得分:5)

通过ADL,在解析非限定函数调用时会考虑关联的命名空间。该行中至少有一个参数与详细命名空间相关联。

  好的,我明白了。这些类型是否继承自详细信息类是否重要? - aaa

是的,基类是用于名称查找的关联类。考虑基类名称空间中的函数(§3.4.2/ 2,第二个项目符号点)。

如果要强制使用:: tensor :: contract,请不要使用非限定名称:

::tensor::contract(alpha * alpha_, a, b, beta, c);

或者将函数名称括在括号中,这会禁用ADL:

(contract)(alpha * alpha_, a, b, beta, c);

答案 1 :(得分:3)

第一候选人将有ADL(Argument Dependent Lookup,或Koening的查找)。在没有看到这些模板如何被实例化的情况下很难说,但是为了参数,如果函数的一个参数恰好来自detail命名空间,那么该命名空间将被添加到查找中

这类似于您可能习惯的东西:

namespace test {
   struct X {};
   std::ostream& operator<<( std::ostream&, X const & ) {}
}
int main() {
   test::X x;
   std::cout << x; // [1]
}

在标有[1]的行中,代码位于全局命名空间中,但它在operator<<命名空间内找到test。原因是x是该调用的参数,类型为test::X,因此编译器会查找test命名空间。