标签: argument-dependent-lookup

find()使用重载运算符==

我尝试使用重载的运算符==()在向量中找到一个元素.但是,如果type1在以下代码中使用,则输出为1和0(未找到).使用type2给出1和1.环境是Xubuntu 12.04和g ++版本4.6.3.

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef pair<string, int> type1;
struct type2: public type1 {};
#define TYPE type1

bool operator== (const TYPE& lhs, const TYPE& rhs) {
    return lhs.first == rhs.first;
}

int main()
{
    vector<TYPE> vec;
    TYPE v1, v2;

    v1.first = "abc"; v1.second = 1; vec.push_back(v1);
    v2.first = "abc"; v2.second = 2;

    cout << (v1 == v2) << endl;
    cout << (find(vec.begin(), vec.end(), v2) != vec.end()) << endl;
}
Run Code Online (Sandbox Code Playgroud)

c++ operator-overloading overload-resolution name-lookup argument-dependent-lookup

8
推荐指数
2
解决办法
1783
查看次数

模板对象的模板友元函数和命名空间

在下面的C++示例代码中,GCC 6和Clang 3.8不同意正确的行为:

这个人为的例子"有效" - 就像GCC 中的test()函数返回一样o.p.在clang中,它调用(undefined)函数get<int, int, float, double>:

template<typename ...Args>
class obj {
 bool p = false;

 template<typename T, typename... Args2>
 friend T get(const obj<Args2...> &o) { return o.p; }
};

template<typename T, typename... Args>
T get(const obj<Args...> &o);


bool test(const obj<int, float, double> &a) {
 return get<int>(a);
}
Run Code Online (Sandbox Code Playgroud)

将相同的代码放在命名空间中会导致GCC执行与clang相同的操作.

namespace ns {

template<typename ...Args>
class obj {
 bool p = false;

 template<typename T, typename... Args2>
 friend T get(const obj<Args2...> &o) { …
Run Code Online (Sandbox Code Playgroud)

c++ templates friend argument-dependent-lookup

8
推荐指数
1
解决办法
309
查看次数

关于友元函数定义和命名空间范围

我正在阅读这篇博客文章部分,并尝试使用提供的代码段.

namespace N {
// 2
class A {
friend void f(A) {} // 1
};
}
Run Code Online (Sandbox Code Playgroud)

如果我理解正确,那么定义// 1将注入名称f所在// 2的位置.但是它只能通过参数依赖查找来获得.精细.

帖子里有一句引起我注意的句子:

7.3.1.2/3命名空间成员定义[namespace.memdef] p3

首先在名称空间中声明的每个名称都是该名称空间的成员.如果非本地类中的友元声明首先声明了类,函数,类模板或函数模板,则该友元是最内层封闭命名空间的成员.友元声明本身不会使名称对非限定查找(3.4.1)或限定查找(3.4.3)可见.

请注意,没有任何地方声明,友元声明引入的名称必须与声明和/或定义的类的名称有任何特定的关系,或者与该类的任何特定关系(就此而言).

由此,我认为以下代码段是有效的:

namespace N {
struct A {
};

struct B {
  friend void f(A) {
}
};

int main() {
  N::A a;
  f(a);
}
Run Code Online (Sandbox Code Playgroud)

但它被GCC7和Clang 4都拒绝了.

t.cpp:19:3:错误:在此范围内未声明'f'

有趣的是,当我尝试f使用N::B对象调用时,我收到以下错误:

t.cpp:12:6:错误:无法将'b'从'N :: B'转换为'N :: A'

所以这是我的问题:

f(A)应该通过ADL检测到?由于这两个类都在命名空间中,我不明白为什么会失败.我查看了标准关于朋友的部分,但未找到相关部分.

我想知道f(A)注入了哪个范围,因为当我尝试通过调用给出错误的参数类型时,GCC能够找到它f(B).

c++ friend argument-dependent-lookup

8
推荐指数
1
解决办法
274
查看次数

为什么std :: swap不使用swap idiom?

正确使用std :: swap是:

using std::swap;
swap(a,b);
Run Code Online (Sandbox Code Playgroud)

它有点冗长,但它确保如果a,b有更好的交换定义它将被选中.

所以现在我的问题是为什么std::swap没有使用这种技术实现,所以用户代码只需要调用std::swap

所以这样的事情(noexcept为了简洁而忽略和约束):

namespace std {
    namespace internal {
        template <class T>      // normal swap implementation
        void swap(T& a, T& b) { // not intended to be called directly
            T tmp = std::move(a);
            a = std::move(b);
            b = std::move(tmp);
        }
    }

    template <class T>
    void swap(T& a, T& b) {
        using internal::swap;
        swap(a,b);
    }
}
Run Code Online (Sandbox Code Playgroud)

c++ template-function argument-dependent-lookup customization-point

8
推荐指数
1
解决办法
340
查看次数

自定义容器迭代器是否保证ADL考虑命名空间std?

我无意在实际代码中使用它.我承诺.

std当函数参数是类型container::iteratorcontainer::iterator不是typedef内置类型时,标准是否保证找到命名空间?

例如

#include <set>
#include <algorithm>
int main()
{
   std::set<int> s;
   find(s.begin(), s.end(), 0); //do I have a guarantee that std::find will be found?
}
Run Code Online (Sandbox Code Playgroud)

换句话说,迭代器类是否可以在stdADL不考虑的命名空间中定义?

提前致谢.

c++ iterator stl std argument-dependent-lookup

7
推荐指数
2
解决办法
174
查看次数

为什么'std :: endl'在语句'std :: cout << std :: endl;"中使用时需要命名空间限定,给定参数依赖查找?

我正在查看关于参数依赖查找的维基百科条目,并且(2014年1月4日)给出了以下示例:

#include<iostream>

int main() 
{
  std::cout << "Hello World, where did operator<<() come from?" << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

......有以下评论:

请注意,std :: endl是一个函数,但它需要完全限定,因为它被用作operator <<的参数(std :: endl是函数指针,而不是函数调用).

我的想法是评论不正确(或根本不清楚).我正在考虑更改评论,而不是

请注意,std :: endl需要完全限定,因为ADL不适用于函数调用的参数 ; 它只适用于函数名称本身.

我是否认为维基百科的评论不正确?我建议的改变是否正确?(即,在这个例子中,我对ADL的理解是正确的吗?)

c++ argument-dependent-lookup

7
推荐指数
1
解决办法
377
查看次数

ADL在constexpr函数中不起作用(仅适用于clang)

以下代码使用MSVC和gcc进行编译,但不能使用clang进行编译。为什么?

如果CallFoo ()is的话,似乎ADL无法正常工作constexpr。查看评论。

template <class T>
constexpr void CallFoo  ()          // Remove constexpr to fix clang compilation error.
{
    Foo (T ());
}


class Apple {};


int main ()
{
    CallFoo<Apple> ();
}


constexpr void Foo (Apple)
{
}
Run Code Online (Sandbox Code Playgroud)

Clang错误消息(请参阅godbolt.org):

<source>:4:5: error: use of undeclared identifier 'Foo'
    Foo (T ());
    ^
<source>:13:5: note: in instantiation of function template specialization 'CallFoo<Apple>' requested here
    CallFoo<Apple> ();
    ^
Run Code Online (Sandbox Code Playgroud)

c++ templates clang argument-dependent-lookup constexpr

7
推荐指数
1
解决办法
92
查看次数

基于参数的依赖名称查找

在cppreference.com上的描述

模板中使用的从属名称的查找被推迟到知道模板参数为止,这时ADL会检查具有外部链接的函数声明,这些声明从模板定义上下文模板实例化上下文中可见。

与此相反,以下代码片段可以使用三个编译器(MSVC,clang和gcc)很好地进行编译:

template <class T>
void CallFoo ()
{
    Foo (T ());
}


class Apple {};


int main ()
{
    CallFoo<Apple> ();
}


static void Foo (Apple)
{
}
Run Code Online (Sandbox Code Playgroud)

Foo是以下内容中的从属名称CallFoo:它取决于模板参数T。但是,Foo尽管违反了上面引用的两个规则,但是编译器仍然可以找到该函数。

  • Foo从的定义或实例中都看不到的声明CallFoo,因为它位于两者之下。
  • Foo 有内部联系。

这三个编译器都不可能有错误。我可能误会了一些东西。您能详细说明一下吗?

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

7
推荐指数
1
解决办法
126
查看次数

C++20 中模板的参数依赖查找

下面的程序在 C++20 中编译得很好:

#include <memory>

struct A{ virtual ~A() = default; };
struct B: A {};

int main()
{
    std::shared_ptr<A> p = std::make_shared<B>();
    auto x = dynamic_pointer_cast<A>(p);
}

Run Code Online (Sandbox Code Playgroud)

但是在 C++17 中它会产生一个错误:

<source>: In function 'int main()':
<source>:9:14: error: 'dynamic_pointer_cast' was not declared in this scope; did you mean 'std::dynamic_pointer_cast'?
    9 |     auto x = dynamic_pointer_cast<A>(p);
      |              ^~~~~~~~~~~~~~~~~~~~
      |              std::dynamic_pointer_cast
In file included from /opt/compiler-explorer/gcc-11.1.0/include/c++/11.1.0/memory:77,
                 from <source>:1:
Run Code Online (Sandbox Code Playgroud)

你能告诉我在 C++20 中有什么改变使它工作吗?

c++ argument-dependent-lookup c++20

7
推荐指数
1
解决办法
137
查看次数

为什么使用 ADL 时 `std::ranges::size` 需要非常量方法?

否则,如果 Ranges::disable_sized_range<std::remove_cv_t<T>> 为 false,则 size(t) 转换为其衰减类型,并且转换后的表达式有效且具有类似整数的类型,其中重载解析通过以下命令执行以下候选人:

  • void size(auto&) = delete;
  • void size(const auto&) = delete; 1
class Test {
    friend size_t size(/*const*/ Test&) {
        return 0;
    }
};

int main() {
    std::ranges::size(Test{});
    // no matching function error when adding the `const` qualifier
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/79e5vrKrT


一般来说,方法size不需要std::size.

为什么会有这样的限制呢std::ranges::size?(好像只有非会员版才能执行。)

c++ argument-dependent-lookup c++20 std-ranges

7
推荐指数
1
解决办法
1562
查看次数