Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/unit-testing/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Can';t在Catch测试中使用重载比较运算符_C++_Unit Testing_Operator Overloading_Catch2 - Fatal编程技术网

C++ Can';t在Catch测试中使用重载比较运算符

C++ Can';t在Catch测试中使用重载比较运算符,c++,unit-testing,operator-overloading,catch2,C++,Unit Testing,Operator Overloading,Catch2,我使用Catch 2.11.1进行了一个简单的单元测试: #define CATCH_CONFIG_MAIN #include "catch.hpp" #include <utility> #include <any> namespace A::B { namespace C { struct S { }; } using type = std::pair<C::S, std::an

我使用Catch 2.11.1进行了一个简单的单元测试:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"
#include <utility>
#include <any>

namespace A::B
{
    namespace C
    {
        struct S
        {
        };
    }

    using type = std::pair<C::S, std::any>;
}

inline bool operator==(A::B::type const&, A::B::type const&)
{
    return true;
}

TEST_CASE("test", "[test]")
{
    auto t1 = std::make_pair(A::B::C::S(), std::any());
    auto t2 = std::make_pair(A::B::C::S(), std::any());

    REQUIRE(t1 == t2);
}
这是Catch的问题,还是我的操作符函数的问题


注意:我正在Debian SID上构建GCC 9.2的最新版本

$ g++ --version
g++ (Debian 9.2.1-23) 9.2.1 20200110
Copyright (C) 2019 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

扩展操作数以提供良好诊断输出的魔力有时会失效

解决方法是使用一些括号禁用该选项:

REQUIRE((t1 == t2));
这实际上是与变量相同的解决方法


文件。在您的案例中,触发这种情况的确切原因我不确定,但从堆栈跟踪中注意到,您的
操作符==
实际上没有被调用,而是
Catch::BinaryExpr::operator==
Catch::compareEqual
,它似乎没有访问权限(或者选择不使用)您的实现。无论哪种方法,解决方案都是如上所述禁用分解机制。

请注意,即使使用Lightness建议的括号,您显示的代码也异常脆弱

我猜您最初是在ADL领域,因为宏中的依赖名称查找(请参阅的最后注释),并且您的代码显然不适合ADL。添加括号会使整个过程只是一个不合格的查找,而不仅仅是ADL(再次,一个猜测)。在这种情况下,非限定查找的非ADL部分为您节省了时间,但它将与完全无关的代码更改分离

考虑这段代码而不是
测试用例
,使用括号大概可以归结为:

namespace test
{
    bool foo()
    {
        auto t1 = std::make_pair(A::B::C::S(), std::any());
        auto t2 = std::make_pair(A::B::C::S(), std::any());

        return t1 == t2;
    }
}
这将按照预期进行编译和工作:

现在在全局
操作符==
t1==t2
之间添加一个完全不相关的
操作符==

namespace test
{
    struct X{};
    bool operator==(X, X);

    bool foo()
    {
        auto t1 = std::make_pair(A::B::C::S(), std::any());
        auto t2 = std::make_pair(A::B::C::S(), std::any());

        return t1 == t2;
    }
}
而你就要出局了:

找不到全局命名空间中的
运算符==
,因为(非ADL部分)非限定名称查找在包含任何
运算符==
的第一个封闭范围内停止。由于这没有发现任何有用的东西,它转而使用内置的
std::pair
比较运算符(通过ADL找到),这将不起作用

只需将运算符重载放在它们操作的对象的名称空间中。因此,不要让
std
(或其他不允许接触的名称空间)中的设施的运算符过载


从评论中添加:

该标准目前还表示,模板参数的名称空间是被考虑的,因此将
操作符==
放在
名称空间C
中是可行的(因为std::pair的第一个模板参数来自于此):

然而,1。这与您的类型别名和2不太匹配。有一些运动使ADL变得不那么疯狂,我看到了关于去掉“考虑模板参数的名称空间”的讨论。见:

我们究竟为什么要研究模板参数的名称空间?其中的任何内容都不可能是该类型接口的一部分,除非模板参数也是基类或其他内容。-萨特药草


我不知道这篇文章今天的立场,但我会避免在新代码中依赖这种ADL。

什么是
要求的
不同之处?我想你知道,但是,只要有什么东西依赖ADL来找到你的操作符,那么所显示的代码就会失败。@MaxLanghof事实上,现在你提到了它,我相信这正是发生的事情here@LightnessRacesBY-SA3.0那么(根据您的回答)为什么要使用括号呢?或者不是吗?@MaxLanghof和帕伦斯一起,它只是一个bog标准,所以ADL不被依赖,对吗?因为该函数在作用域中。这是我第一次尝试,将运算符放在
A::B
命名空间中。它仍然不起作用,但更糟糕的是,Lightness Races by-SA3.0(使用括号)的解决方案不再起作用。因此,是的,我的设计中确实存在很多脆弱性,我可能应该重新考虑一下。@Someprogrammerdude的
操作符==
std::pair
上运行,因此必须在
命名空间std
中才能找到它。该标准目前还表示,模板参数的名称空间是被考虑的,因此将
运算符==
放在
名称空间C
中是可行的(因为
std::pair
的第一个模板参数来自于此),但这是1。与您的
类型
别名和2不太匹配。有一些运动使ADL变得不那么疯狂,“考虑模板参数的名称空间”是afaik的砧板。看,找不到后者的源…根据您的回答,我将
类型
转换为一个新结构,并将比较运算符移动到
a::B
命名空间中。它现在运行良好。
REQUIRE((t1 == t2));
namespace test
{
    bool foo()
    {
        auto t1 = std::make_pair(A::B::C::S(), std::any());
        auto t2 = std::make_pair(A::B::C::S(), std::any());

        return t1 == t2;
    }
}
namespace test
{
    struct X{};
    bool operator==(X, X);

    bool foo()
    {
        auto t1 = std::make_pair(A::B::C::S(), std::any());
        auto t2 = std::make_pair(A::B::C::S(), std::any());

        return t1 == t2;
    }
}