首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++重载解析规则中的缺陷?

C++重载解析规则中的缺陷?
EN

Stack Overflow用户
提问于 2016-02-26 01:23:09
回答 2查看 183关注 0票数 8

考虑以下代码:

代码语言:javascript
复制
#include <iostream>

namespace ns1
{
    struct A
    {
    };

    template <class T>
    std::ostream& operator << (std::ostream& os, const T& t)
    {
        return os << "ns1::print" << std::endl;
    }
}

namespace ns2
{
    template <class T>
    std::ostream& operator << (std::ostream& os, const T& t)
    {
        return os << "ns2::print" << std::endl;
    }

    void f (const ns1::A& a)
    {
        std::cout << a;
    }
}


int main()
{
    ns1::A a;

    ns2::f (a);

    return 0;
}

按照标准,编译失败并出现“歧义重载错误”。

但是为什么呢?A的“home”命名空间中的“同样好”的运算符肯定应该优先吗?有没有什么合理的理由不去做呢?

EN

回答 2

Stack Overflow用户

发布于 2016-02-26 01:38:39

如果你想让namespace A中的重载成为首选,那么你必须在其中添加一些东西来使它变得更好。比方说,让它不再是一个模板:

代码语言:javascript
复制
namespace ns1 
{
    std::ostream& operator<<(std::ostream&, const A& );
}

否则,如果一个名称空间中的函数模板与另一个名称空间中的函数模板完全相同,那么就没有任何概念性的理由来解释为什么两者更受欢迎。毕竟,为什么A的名称空间中的函数模板会比f的名称空间中的函数模板“更好”呢?f的实现者不是“更清楚”吗?仅仅依靠函数签名可以回避这个问题。

票数 10
EN

Stack Overflow用户

发布于 2016-02-26 04:22:11

如果仔细阅读编译器错误,就会发现歧义错误不是发生在ns1ns2中的operator<<版本之间,而是发生在ns1operator<<(os, const char*)实例化和namespace std的完全相同的重载之间。后者正被std::ostream上的ADL所拖累。

最好的方法是使用@Barry的建议,并在名称空间ns1中取消operator<<的模板化,但也要将所有与ns1::A相关的功能(如f(A))添加到同一名称空间中:

代码语言:javascript
复制
#include <iostream>

namespace ns1
{
    struct A {};

    std::ostream& operator << (std::ostream& os, const A& t)
    {
        return os << "ns1::print" << std::endl;
    }

    void f (const A& a)
    {
        std::cout << a;
    }    
}

int main()
{
    ns1::A a;
    f(a); // rely on ADL to find ns1::operator<<(os, A)
}

命名空间ns1随后通过ADL充当class A的更广泛的接口。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35634091

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档