C++名称空间解析(基于参数的“自动using”)?

4

当我从命名空间外调用一个在命名空间中声明的函数时,通常需要用命名空间显式前缀:

namespace ns1 {
    void myfunc();
}

myfunc();        // compiler complains
ns1::myfunc();   // good

然而,我遇到了这样一种情况:编译器似乎可以自动推断出我想要使用的函数。
namespace mymath {
    struct Vector3 {
        float x, y, z;
    };
    Vector3 vector_cross(const Vector3& lhs, const Vector3 &rhs)
    {
        return lhs; // Pretend this is a cross product
    }
} // ns

int main(int argc, char** argv)
{
    mymath::Vector3 v, w, x;
    x = vector_cross(v, w);   // <---- Here, I do not need to
                              //       prefix with the namespace
    return 0;
}

Q1:是因为编译器可以根据参数类型自动选择适当的函数吗?还是其他原因?


经过更多测试,我发现如果我在另一个命名空间中添加具有相同声明的另一个函数,我的编译器不会报错:

namespace mymath {
    // same as above
} // ns

namespace math2 {
    mymath::Vector3 vector_cross(const mymath::Vector3& lhs, const mymath::Vector3 &rhs)
    {
        return rhs; // Return rhs this time
    }
} // ns

int main(int argc, char** argv)
{
    mymath::Vector3 v, w, x;
    x = vector_cross(v, w);   // <---- Here, which one did the compiler chose?
    return 0;
}

Q2:如何取消这个行为?

编辑: 我的编译器:gcc版本4.7.2(Debian 4.7.2-5)


7
“Argument dependent lookup” 是一个搜索术语。 - GManNickG
你应该尝试发布一个可工作的示例的原因之一是它表明你已经尝试过这样的示例,而要使上述代码执行你所说的操作的唯一方法是具有“using”语句或从在mymath范围内的某个地方调用vector_cross。我建议你努力寻找一个最小的可重现示例,这将揭示原因。 - kfsone
@kfsone:我自己尝试过这样的例子,只是为了缩短问题而去掉了main()函数--我把它放回来了,这样大家就可以复制/粘贴代码了。然而,我根本没有使用任何using语句。 - Julien-L
抱歉,我无法在您的编辑粘贴后重新创建未能正常工作的版本。只好使用 ADL 了 :( - kfsone
1个回答

5

问题1:'appropriate'存在争议,但基本上是选择将所有“相关”命名空间组合的功能,对于许多样本而言运行良好。

问题2:你可以让几十个人加入WG21,并最终投票支持其中一个“修复ADL”的提案,但到目前为止,这些尝试都失败了。

问题2,实用回答:ADL仅适用于未经限定的查找,因此您始终可以使用限定名称(前缀::std::等)。或者完全停止使用命名空间。除此之外,您还受到“Koenig不确定性原理”的影响。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接