在下面的代码中,有人可以解释为什么如果启用了用“ifdef TEST”定界的代码,为什么我定义的用于打印枚举的operator <
如果我使用g++ filename.cpp构建,则输出为:

Print for Container: mycolor is red

如果我使用g++ -DTEST filename.cpp进行构建,则输出为:
Print for Container: mycolor is 0

代码如下:
#包括
namespace mynamespace
{
    enum color {red, blue};
}
namespace mynamespace
{
    class Container
    {
    public:
        mynamespace::color mycolor1;
        explicit Container() : mycolor1(mynamespace::red) {};
        std::ostream &Print(std::ostream& os) const;
    };
    class Container2
    {
    };
}
std::ostream & operator<<(std::ostream &os, const mynamespace::color &_color);

namespace mynamespace
{
#ifdef TEST
// If this is defined, the printing of the enum in Container does not use the operator<< function to output the enum as a string
std::ostream& operator<<(std::ostream &os, const Container2 &i);
#endif
}

int main()
{
    // Create a Container.  Default color is red
    mynamespace::Container *container = new mynamespace::Container;
    container->Print(std::cout);
}

std::ostream & mynamespace::Container::Print(std::ostream &os) const
{
    os << "Print for Container: mycolor is " << mycolor1 << std::endl;
    return os;
}
std::ostream& operator<<(std::ostream &os, const mynamespace::color &_color)
{
    switch(_color)
    {
        case mynamespace::red: os << "red"; break;
        case mynamespace::blue: os << "blue"; break;
        default: os << "unknown"; break;
    }
    return os;
}

最佳答案

简化示例:

namespace mynamespace
{
    enum color {red, blue};

    class Container
    {
    public:
        mynamespace::color mycolor1;
        explicit Container() : mycolor1(mynamespace::red) {};
        std::ostream &Print(std::ostream& os) const;
    };
    class Container2
    {
    };

    std::ostream& operator<<(std::ostream &os, const Container2 &i);
}
std::ostream & operator<<(std::ostream &os, const mynamespace::color &_color);

std::ostream & mynamespace::Container::Print(std::ostream &os) const
{
    os << mycolor1 << std::endl;
    return os;
}

表达式os << mycolor1寻找一个名为operator<<的函数。该函数将作为std::ostream的成员函数进行搜索,并且(独立地,另外)通过不合格的查找进行搜索,从而触发ADL。

通过ADL进行的不合格查找将找到mynamespace::operator<<
“纯”不合格查找(无ADL)将从Print函数体的范围开始,该范围是Container(*)类的范围,并遍历周围的范围,直到找到名为operator<<的函数。然后停止。在这里,它也停止在mynamespace上:这是第一个具有该名称功能的周围范围。不搜索全局 namespace 。

您可以使“纯”不合格的查找找到全局函数,例如通过说:
std::ostream & mynamespace::Container::Print(std::ostream &os) const
{
    using ::operator<<;
    os << mycolor1 << std::endl;
    return os;
}

(*)您可以将其视为
namespace mynamespace { enum color {red, blue}; class Container2; }

std::ostream& operator<<(std::ostream &os, const mynamespace::color &_color);

namespace mynamespace
{
    std::ostream & operator<<(std::ostream &os, const Container2 &i);

    class Container
    {
    public:
        mynamespace::color mycolor1;
        explicit Container() : mycolor1(mynamespace::red) {};

        std::ostream &Print(std::ostream& os) const
        {
            os << mycolor1 << std::endl;
            return os;
        }
    };
};

在这里,可能更清楚的是,包含名为os << mycolor1的函数的operator<<的第一个周围范围是mynamespace

恕我直言,一个好的解决方案是将枚举的operator<<也放入mynamespace中:
namespace mynamespace
{
    enum color {red, blue};
    std::ostream & operator<<(std::ostream &os, const mynamespace::color &_color);
}

这样,可以通过ADL找到它。

关于c++ - 为什么不使用用于枚举的operator <<?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/19793523/

10-10 21:22
查看更多