标签: argument-dependent-lookup

什么`在类方法实现的主体内使用std :: swap`意味着什么?

在一些c ++实践中,我试图学习并采用复制交换习语,对这个问题进行彻底的解释:复制交换习语.

但我发现了一些我从未见过的代码:using std::swap; // allow ADL在这个例子中

class dumb_array
{
public:
    // ...

    void swap(dumb_array& pOther) // nothrow
    {
        using std::swap; // allow ADL    /* <===== THE LINE I DONT UNDERSTAND */

        swap(mSize, pOther.mSize); // with the internal members swapped,
        swap(mArray, pOther.mArray); // *this and pOther are effectively swapped
    }
};
Run Code Online (Sandbox Code Playgroud)
  1. using std::swap;在函数实现的主体内部意味着什么?
  2. ADL是什么意思?

c++ stl using std argument-dependent-lookup

26
推荐指数
2
解决办法
5310
查看次数

为什么Argument Dependent Lookup不能与函数模板dynamic_pointer_cast一起使用

考虑以下C++程序:

#include <memory>

struct A {};

struct B : A {};

int main()
{
    auto x = std::make_shared<A>();
    if (auto p = dynamic_pointer_cast<B>(x));
}
Run Code Online (Sandbox Code Playgroud)

使用MSVC 2010进行编译时,我收到以下错误:

error C2065: 'dynamic_pointer_cast' : undeclared identifier
Run Code Online (Sandbox Code Playgroud)

如果auto被替换,则错误仍然存​​在std::shared_ptr<A>.当我完全符合要求时std::dynamic_pointer_cast,程序会成功编译.

另外,gcc 4.5.1也不喜欢它:

error: 'dynamic_pointer_cast' was not declared in this scope
Run Code Online (Sandbox Code Playgroud)

我认为Koenig查找std::dynamic_pointer_cast会选择它,因为命名空间中的生命类型.我在这里错过了什么?xstd

c++ argument-dependent-lookup

26
推荐指数
2
解决办法
1931
查看次数

ADL是调用朋友内联函数的唯一方法吗?

让我们在声明中定义f:作为朋友的函数:SS

struct S
{
    friend void f() {}
};
Run Code Online (Sandbox Code Playgroud)

我找不到打电话的方法f.

那么,这样的内联友元函数只能通过依赖参数的查找来调用吗?

struct S
{
    friend void f() {}
    friend void g(S const&) {}
} const s;

int main()
{
    // f();     // error: 'f' was not declared in this scope
    // S::f();  // error: 'f' is not a member of 'S'
    g(s);
    // S::g(s); // error: 'g' is not a member of 'S'
}
Run Code Online (Sandbox Code Playgroud)

额外奖励:如果我想获得函数指针/ std::function/ lambda g怎么办?

c++ friend language-lawyer name-lookup argument-dependent-lookup

24
推荐指数
2
解决办法
1027
查看次数

从元组中获取元素

可能重复:
为什么ADL没有找到功能模板?

调用get似乎不会调用依赖于参数的查找:

auto t = std::make_tuple(false, false, true);
bool a = get<0>(t);        // error
bool b = std::get<0>(t);   // okay
Run Code Online (Sandbox Code Playgroud)

g ++ 4.6.0说:

error: 'get' was not declared in this scope
Run Code Online (Sandbox Code Playgroud)

Visual Studio 2010说:

error C2065: 'get': undeclared identifier
Run Code Online (Sandbox Code Playgroud)

为什么?

c++ templates tuples argument-dependent-lookup c++11

23
推荐指数
2
解决办法
2699
查看次数

为什么这个调用swap()模棱两可?

以下程序

#include <algorithm>
#include <utility>
#include <memory>

namespace my_namespace
{


template<class T>
void swap(T& a, T& b)
{
  T tmp = std::move(a);
  a = std::move(b);
  b = std::move(tmp);
}

template<class T, class Alloc = std::allocator<T>>
class foo {};

}

int main()
{
  my_namespace::foo<int> *a, *b;

  using my_namespace::swap;

  swap(a,b);

  return 0;
}
Run Code Online (Sandbox Code Playgroud)

导致两者g++clang在我的系统上发出以下编译器错误:

$ clang -std=c++11 swap_repro.cpp -I.
swap_repro.cpp:28:3: error: call to 'swap' is ambiguous
  swap(a,b);
  ^~~~
/usr/bin/../lib/gcc/x86_64-linux-gnu/5.2.1/../../../../include/c++/5.2.1/bits/algorithmfwd.h:571:5: note: candidate function [with _Tp = my_namespace::foo<int, std::allocator<int> > …
Run Code Online (Sandbox Code Playgroud)

c++ namespaces class-template name-lookup argument-dependent-lookup

23
推荐指数
2
解决办法
1643
查看次数

具有类参数的函数是否从命名空间泄露?

我在这里有一小段代码供您考虑,这让我感到非常困惑.奇怪的是,它在Sun Studio和GCC上编译,即使我认为它不应该.

考虑一下:

namespace name
{
  class C
    {
      int a;
    };

  void f(C c);
  void g(int a);
}

int main(int argc, char** argv)
{
  name::C c;

  name::f(c); 
  f(c);  // <--- this compiles, strangely enough

  name::g(42);
  // g(42);  <--- this does not, as I expected
}
Run Code Online (Sandbox Code Playgroud)

来自同一命名空间的类参数会导致函数f"泄漏"到命名空间之外,并且无需访问name::.

有人对此有解释吗?这当然是我而不是编译器在这里错了.

c++ namespaces argument-dependent-lookup

22
推荐指数
3
解决办法
943
查看次数

GCC,Clang和IBM不同意如何执行依赖于模板参数的名称查找.哪一个是对的?

考虑一下我在IBM网站上找到的这个例子:

#include <iostream>
using namespace std;

void f(double) { cout << "Function f(double)" << endl; }

template<class T> void g(T a) {
  f(123);
  h(a);
}

void f(int) { cout << "Function f(int)" << endl; }
void h(double) { cout << "Function h(double)" << endl; }

void i() {
  extern void h(int);
  g<int>(234);
}

void h(int) { cout << "Function h(int)" << endl; }

int main(void) {
    i();
}
Run Code Online (Sandbox Code Playgroud)

它会打印什么?

  • 在这里修改了这个例子的IBM文档说它会打印:

    Function f(double)
    Function h(double)
    
    Run Code Online (Sandbox Code Playgroud)

    这个的基本原理是模板参数依赖的名称查找是在实例化之前执行的i(),所以它找到h(double) …

c++ templates argument-dependent-lookup

22
推荐指数
1
解决办法
534
查看次数

使用命名空间 std 导致 boost 指针转换触发 C++17 标准中的 ADL

我有一个带有继承和shared_ptr来自 boost 库的简单代码。使用标准 c++20,代码可以正常编译。函数调用static_pointer_castdynamic_pointer_cast编译无需预先boost::命名空间——这些函数调用之所以有效,是因为 ADL(参数相关查找)。

但对于标准 c++17,代码将无法编译。我认为 ADL 没有实现,或者实现方式不同。但是,如果我添加using namespace std,代码就可以正常编译。我的问题是:与库的函数调用std有什么关系?boost

这是在线编译器,因此您可以通过注释行中和注释行来进行操作using namespace std;: https: //godbolt.org/z/cz8Md5Ezf

#include <iostream>
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>

// using namespace std;

class Animal {
public:
  Animal()
  {}
  virtual ~Animal()
  {}
  void speak()
  {
    std::cout << "I am an animal\n";
  }
};

class Dog : public Animal {
public:
  Dog()
  {}
  void bark()
  {
    std::cout << "Gheu --> ";
  }
  void …
Run Code Online (Sandbox Code Playgroud)

c++ boost argument-dependent-lookup c++17 c++20

20
推荐指数
1
解决办法
996
查看次数

基于范围的语句定义冗余

查看n3092,在§6.5.4中,我们找到了基于范围的for循环的等价性.然后它继续说什么__begin__end等于.它区分了数组和其他类型,我觉得这是多余的(也就是令人困惑).

它表示数组类型__begin__end你所期望的:指向第一个的指针和指向一个结尾的指针.那么对于其他类型的,__begin__end等于begin(__range)end(__range),与ADL.命名空间std是关联的,以便在第24.6.5节中找到std::beginstd::end定义<iterator>.

但是,如果我们看的定义std::beginstd::end,他们是阵列以及容器类型都定义.并且数组版本与上面完全相同:指向第一个的指针,指向一个结尾的指针.

为什么需要将数组与其他类型区分开来,当为其他类型提供的定义同样适用时,查找std::beginstd::end


为方便起见,有些删节报价:

§6.5.4基于范围的for陈述

- 如果_RangeT是一个数组类型,则begin-expr和end-expr分别是__range和__range + __bound,其中__bound是数组绑定的.如果_RangeT是未知大小的数组或不完整类型的数组,则程序格式错误.

- 否则,begin-expr和end-expr分别是begin(__ range)和end(__ range),其中begin和end通过参数依赖查找(3.4.2)查找.出于此名称查找的目的,名称空间std是关联的名称空间.

§24.6.5范围访问

template <class T, size_t N> T* begin(T (&array)[N]);
Run Code Online (Sandbox Code Playgroud)

返回:数组.

template <class T, size_t N> T* end(T (&array)[N]);
Run Code Online (Sandbox Code Playgroud)

返回:数组+ N.

c++ for-loop range argument-dependent-lookup c++11

19
推荐指数
1
解决办法
3459
查看次数

在C++模板实例化中查找依赖名称

当我尝试编译此代码时

// void foobar(int); 

template <class T>
struct Foo {
  void bar(T t) { foobar(t); };
};

void foobar(int);

template class Foo<int>;
Run Code Online (Sandbox Code Playgroud)

使用g ++ 4.8.2我收到以下错误消息

foo.cc: In instantiation of ‘void Foo<T>::bar(T) [with T = int]’:
foo.cc:10:16:   required from here
foo.cc:5:27: error: ‘foobar’ was not declared in this scope, and no 
             declarations were found by argument-dependent lookup at 
               the point of instantiation [-fpermissive]
   void bar(T t) { foobar(t); };
                           ^
foo.cc:8:6: note: ‘void foobar(int)’ declared here, later in the translation unit …
Run Code Online (Sandbox Code Playgroud)

c++ templates language-lawyer argument-dependent-lookup

19
推荐指数
2
解决办法
1192
查看次数