C ++运算符查找规则/ Koenig查找 [英] C++ operator lookup rules / Koenig lookup

查看:97
本文介绍了C ++运算符查找规则/ Koenig查找的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在编写测试套件时,我需要提供 operator<<(std :: ostream& ... 的实现,以供Boost单元测试使用。 / p>

这可行:

 命名空间theseus {命名空间核心{
std :: ostream&运算符<(std :: ostream& ss,const PixelRGB& p){
return(ss< PixelRGB(<<(int)pr<< ;,<<(int)pg<<,<<(int)pb<<<));
}
}}

这不是:

  std :: ostream&运算符<((std :: ostream& ss,const theseus :: core :: PixelRGB& p){
return(ss<< PixelRGB(< ;<(int)pr<,<<(int)pg<< ,,<<(int)pb<<)));
}

显然,当g ++尝试解决对的使用时,第二个未包含在候选匹配项中为什么(什么规则导致了这个原因)?



调用 operator<< 的代码深入到Boost单元测试框架中,但这是测试代码:

  BOOST_AUTO_TEST_SUITE(core_image)

BOOST_AUTO_TEST_CASE(test_output){
使用命名空间theseus :: core;
BOOST_TEST_MESSAGE(PixelRGB(5,5,5)); //仅使用运算符<<在someus :: core
std :: cout<<中定义PixelRGB(5,5,5)<< \n; //使用任何定义
BOOST_CHECK(true); //避免出现断言错误
}

BOOST_AUTO_TEST_SUITE_END()

作为参考,我正在使用g ++ 4.4(尽管目前我假设这种行为符合标准)。

解决方案

在依赖于参数的查找(koenig查找的正确名称)中,编译器将重载函数集添加到每个参数的名称空间中声明的函数。



在您的情况下,第一个 operator<< 在名称空间 thesus :: core,中声明。调用运算符的参数。因此,此 operator<< 被认为是ADL,因为它是在关联的命名空间中声明的



在第二种情况下, operator<< 似乎是在不是关联名称空间的全局名称空间中声明的,因为参数类型是名称空间 std 和param 2是来自命名空间 theseus :: core 的类型。



实际上,可能是您的第二个 operator<< 没有在全局名称空间中声明,因为可以通过在父作用域中查找来找到。.也许您还拥有更多类似的东西?如果您可以发布更多代码,我们可以提供更好的答案。






我还记得吗,ADL不会在父级中查找在当前作用域中找到名称时的作用域。因此,boost宏 BOOST_TEST_MESSAGE 扩展为包含 operator<< ,并且在范围树中有一些非在表达式和全局范围之间可行的 operator <<

  #include< iostream> 

命名空间NS1
{
A类
{};

//由于ADL
std :: ostream&运算符<((std :: ostream& ;, NS1 :: A&);
}


//由于未找到NS2 :: foo中的表达式,因此在找到运算符时会停止查找,这是看不到的。在NS2
std :: ostream&运算符<((std :: ostream& ;, NS1 :: A&);

命名空间NS2
{
B类
{};

//如果您对此进行注释,则查找将在父范围
std :: ostream&中进行。运算符<((std :: ostream& ;, B&);

void foo(NS1 :: A& a)
{
std :: cout<<一个;
}
}


While writing a test suite, I needed to provide an implementation of operator<<(std::ostream&... for Boost unit test to use.

This worked:

namespace theseus { namespace core {
    std::ostream& operator<<(std::ostream& ss, const PixelRGB& p) {
        return (ss << "PixelRGB(" << (int)p.r << "," << (int)p.g << "," << (int)p.b << ")");
    }
}}

This didn't:

std::ostream& operator<<(std::ostream& ss, const theseus::core::PixelRGB& p) {
    return (ss << "PixelRGB(" << (int)p.r << "," << (int)p.g << "," << (int)p.b << ")");
}

Apparently, the second wasn't included in the candidate matches when g++ tried to resolve the use of the operator. Why (what rule causes this)?

The code calling operator<< is deep within the Boost unit test framework, but here's the test code:

BOOST_AUTO_TEST_SUITE(core_image)

BOOST_AUTO_TEST_CASE(test_output) {
    using namespace theseus::core;
    BOOST_TEST_MESSAGE(PixelRGB(5,5,5)); // only compiles with operator<< definition inside theseus::core
    std::cout << PixelRGB(5,5,5) << "\n"; // works with either definition
    BOOST_CHECK(true); // prevent no-assertion error
}

BOOST_AUTO_TEST_SUITE_END()

For reference, I'm using g++ 4.4 (though for the moment I'm assuming this behaviour is standards-conformant).

解决方案

In argument dependent lookup (the correct name for koenig lookup) the compiler adds to the overloaded function set the functions which are declared in the namespaces of each parameter.

In your case, the first operator<< is declared in the namespace thesus::core, which is the type of the argument you call the operator with. Therefore this operator<< is considered for ADL because it's declared in an associated namespace

In the second case, the operator<< seems to be declared in the global namespace which is not an associated namespace as parameter one is of type from namespace std and param 2 is of type from namespace theseus::core.

Actually, probably your 2nd operator<< isn't declared in global namespace as that would be found through looking in parent scopes.. maybe you've got something more like this? If you can post more code we can give a better answer.


Ok I remembered, ADL doesn't lookup in parent scopes when it finds a name in the current scope. So the boost macro BOOST_TEST_MESSAGE expands to include an operator<< and there is some in the scope tree a non-viable operator<< between the expression and global scope. I updated code to illustrate this (hopefully).

#include <iostream>

namespace NS1
{
  class A
  {};

  // this is found by expr in NS2 because of ADL
  std::ostream & operator<<(std::ostream &, NS1::A &);
}


// this is not seen because lookup for the expression in NS2::foo stops when it finds the operator<< in NS2
std::ostream & operator<<(std::ostream &, NS1::A &);

namespace NS2
{
    class B
    {};

    // if you comment this out lookup will look in the parent scope
    std::ostream & operator<<(std::ostream &, B &);

    void foo(NS1::A &a)
    {
        std::cout << a;
    }  
}

这篇关于C ++运算符查找规则/ Koenig查找的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆