【问题标题】:Boost test fails with enum classes inside namespacesBoost 测试因命名空间内的枚举类而失败
【发布时间】:2015-11-24 02:52:27
【问题描述】:

如果您为 C++11 的 enum class 定义了一个 operator <<,那么您可以成功地将其与 Boost 的单元测试库一起使用。

但是,如果您将 enum class 放在 namespace 中,则 Boost 代码将不再编译。

为什么将enum class 放入namespace 会阻止它工作? std::cout 两种方式都可以正常工作,所以这肯定意味着operator << 是正确的吗?

以下是一些演示该问题的示例代码:

// g++ -std=c++11 -o test test.cpp -lboost_unit_test_framework
#include <iostream>
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE EnumExample
#include <boost/test/unit_test.hpp>

// Remove this namespace (and every "A::") and the code will compile
namespace A {

enum class Example {
    One,
    Two,
};

} // namespace A

std::ostream& operator<< (std::ostream& s, A::Example e)
{
    switch (e) {
        case A::Example::One: s << "Example::One"; break;
        case A::Example::Two: s << "Example::Two"; break;
    }
    return s;
}

BOOST_AUTO_TEST_CASE(enum_example)
{
    A::Example a = A::Example::One;
    A::Example b = A::Example::Two;

    // The following line works with or without the namespace
    std::cout << a << std::endl;

    // The following line does not work with the namespace - why?
    BOOST_REQUIRE_EQUAL(a, b);
}

【问题讨论】:

    标签: c++ c++11 boost operator-keyword enum-class


    【解决方案1】:

    如果要使用ADL,则需要在命名空间内定义运算符。

    #include <iostream>
    #define BOOST_TEST_DYN_LINK
    #define BOOST_TEST_MODULE EnumExample
    #include <boost/test/unit_test.hpp>
    
    namespace A {
    
    enum class Example {
        One,
        Two,
    };
    
    
    std::ostream& operator<< (std::ostream& s, Example e)
    {
        switch (e) {
            case A::Example::One: s << "Example::One"; break;
            case A::Example::Two: s << "Example::Two"; break;
        }
        return s;
    }
    
    } // namespace A
    
    BOOST_AUTO_TEST_CASE(enum_example)
    {
        A::Example a = A::Example::One;
        A::Example b = A::Example::Two;
    
        // The following line works with or without the namespace
        std::cout << a << std::endl;
    
        // The following line does not work with the namespace - why?
        BOOST_REQUIRE_EQUAL(a, b);
    }
    

    【讨论】:

    • 啊哈,这就解释了,谢谢!由于我在 .hpp 文件中声明了该函数,因此我必须将 std::ostream&amp; operator&lt;&lt; (std::ostream&amp; s, Example e); 放入命名空间内的 .hpp 中,然后在 .cpp 实现中将其放入 std::ostream&amp; A::operator&lt;&lt; (std::ostream&amp; s, A::Example e) 以便它可以在命名空间。将 .cpp 实现放在另一个 namespace A { } 子句中不起作用。
    • @Malvineous 无论如何,在定义东西时使用完全限定名称是一个好习惯,如果你搞砸了声明,它会在编译而不是链接期间给你一个早期的错误。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 2016-03-27
    相关资源
    最近更新 更多