标签: argument-dependent-lookup

一般来说,加上考虑本地使用声明的decltype

C++ 0x的ranged-for循环有一个处理数组的特殊异常(FDIS§6.5.4),并且有两个函数std :: begin和end,它们被重载以处理数组或选择开始/结束方法.这使我相信可以编写接受通用序列的函数来匹配ranged-for循环的行为:

template<class C>
void f(C &c) {
  using std::begin;
  using std::end;
  do_something_with(begin(c), end(c));
}
Run Code Online (Sandbox Code Playgroud)

如果在C的命名空间中有一个"更具体"的开始/结束,它将通过ADL选择,否则代码"默认"为std :: begin/end.

但是,有一个原因,因为有特殊例外.如果在命名空间中传递一个类型的数组,其中一个语义不同的begin/end接受一个指针,则不会选择std :: begin/end的数组形式:

namespace ns {
  struct A {};
  void begin(A*);  // Does something completely different from std::begin.
}

void f_A() {  // Imagine above f() called with an array of ns::A objects.
  ns::A c[42];
  using std::begin;
  begin(c);  // Selects ns::begin, not array form of std::begin!
}
Run Code Online (Sandbox Code Playgroud)

为了避免这种情况,有没有比编写我自己的开始/结束包装器(内部使用ADL)并显式调用它们而不是std :: begin或ADLized begin更好的解决方案?

namespace my {
  template<class T>
  auto begin(T &c)  // …
Run Code Online (Sandbox Code Playgroud)

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

11
推荐指数
1
解决办法
387
查看次数

在这种情况下,为什么编译器会选择不正确的函数重载?

我正在尝试Sean Parent在GoingNative 2013上的演讲中提出的代码 - "继承是邪恶的基础".(最后一张幻灯片的代码可在https://gist.github.com/berkus/7041546获得

我试图自己实现相同的目标,但我无法理解为什么下面的代码不会按照我的预期行事.

#include <boost/smart_ptr.hpp>
#include <iostream>
#include <ostream>

template <typename T>
void draw(const T& t, std::ostream& out)
{
    std::cout << "Template version" << '\n';
    out << t << '\n';
}

class object_t
{
public:
    template <typename T>
    explicit object_t (T rhs) : self(new model<T>(rhs)) {};

    friend void draw(const object_t& obj, std::ostream& out)
    {
        obj.self->draw(out);
    }

private:
    struct concept_t
    {
        virtual ~concept_t() {};
        virtual void draw(std::ostream&) const = 0;
    };

    template <typename T>
    struct model …
Run Code Online (Sandbox Code Playgroud)

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

11
推荐指数
1
解决办法
744
查看次数

为什么这个程序会交换这些值?

我有以下代码:

#include "stdafx.h"
#include <iostream>
using namespace std;
#include <conio.h>
#include <cstring>
#include <iomanip>

void swap(long a, long b)
{
    long temp;

    temp=a;
    a=b;
    b=temp;
}
int _tmain(int argc, _TCHAR* argv[])
{
    int x = 5, y = 3;
    cout << x ;
    cout << y << endl;

    swap(x, y);

    cout << x ;
    cout << y << endl;

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

该程序给出了输出:

5 3

3 5
Run Code Online (Sandbox Code Playgroud)

该程序实际上交换价值!这是为什么?这些参数swap()不是指针或引用.

(我正在使用VS 2005)

c++ swap name-lookup argument-dependent-lookup

10
推荐指数
1
解决办法
378
查看次数

什么是C++名称查找在这里做什么?(&GCC对吧?)

我在一些生产代码中遇到问题,我将其最小化到以下测试用例:

template<typename T>
void intermediate(T t)
{
    func(t); // line 4 ("func not declared in this scope")
}

namespace ns {
    struct type {};
}

void func(ns::type const & p); // line 11 ("declared here, later")

void foo(ns::type exit_node)
{
    intermediate(exit_node);  // line 15 ("required from here")
}
Run Code Online (Sandbox Code Playgroud)

GCC 4.5汇编了这个罚款.有和没有-std=c++11,4.7和4.9产生如下消息:

test.cpp: In instantiation of ‘void intermediate(T) [with T = ns::type]’:
test.cpp:15:27:   required from here
test.cpp:4:5: error: ‘func’ was not declared in this scope, and no declarations were found …
Run Code Online (Sandbox Code Playgroud)

c++ argument-dependent-lookup

10
推荐指数
1
解决办法
231
查看次数

二元运算符的最佳命名空间是什么?

为了优雅,封装和利用ADL(Argument Dependent Lookup)在函数参数的命名空间内定义一个函数是很常见的.

假设我在不同的命名空间中有两个库.有三种情况1)一个是我控制的库的一部分,另一个是第三方(例如Boost),或者2)我控制两者,或者3)我控制没有(只写"胶水"代码).

我有这样的事情,

namespace ns_A{
   struct A{...}; // something that looks like iostream
}
namespace ns_B{
   struct B{...};
}
Run Code Online (Sandbox Code Playgroud)

我想将"流"B流入A,最佳选择是什么

namespace ???{ // what is more correct ns_A, or ns_B?
   A& operator<<(A& a, B const& b){...} 
}
Run Code Online (Sandbox Code Playgroud)

或者我应该把它放在两个名称空间中?

namespace ns_B{
   A& operator<<(A& a, B const& b){...} 
}
namespace ns_A{
   using ns_B::operator<<;
}
Run Code Online (Sandbox Code Playgroud)

哪个是定义像这样的二进制函数的最佳命名空间?

(C++ 11的命名空间内联是否会改变任何建议?)

(我使用这个例子operator<<是因为,在其他条件相同的情况下,直觉上看起来更好namespace ns_B.)


编辑:这是我可以找到的关于名称空间实际使用的最完整的指南和参考 https://www.google.com/amp/s/akrzemi1.wordpress.com/2016/01/16/a-customizable-framework/安培/

c++ argument-dependent-lookup c++11

10
推荐指数
2
解决办法
270
查看次数

表达式中的运算符的GCC和ADL

考虑这个代码示例

template <typename T> struct S { T t; };

template <class T> void foo(const S<T> &v)
{
  bar(v.t);
}

namespace N
{
  struct A {};
} 

void bar(const N::A &a) {}

int main()
{
  S<N::A> a;
  foo(a);    
}
Run Code Online (Sandbox Code Playgroud)

代码无法在GCC和Clang中编译,因为常规查找和ADL都无法解析bar来自的调用foo.这是完全可以预期的,因为bar调用的关联命名空间列表就是这样N.不包括全局命名空间,找不到全局命名空间bar.一切都应该如此.

但是,如果我将其更改为

template <typename T> struct S { T t; };

template <class T> void foo(const S<T> &v)
{
  +v.t;
}

namespace N
{
  struct A {};
} 

void operator +(const …
Run Code Online (Sandbox Code Playgroud)

c++ gcc operator-overloading language-lawyer argument-dependent-lookup

10
推荐指数
1
解决办法
135
查看次数

为什么发明了依赖于参数的查找?

为什么发明了依赖于参数的查找(ADL)?是这样我们可以写cout << stuff而不是std::operator<<(cout, stuff)?如果是这种情况,为什么ADL不限于运营商而不是所有功能?

如果C++有其他方法来执行内置和用户定义类型的通用输出,例如类型安全的printf可变参数模板,是否可以防止引入ADL ?

c++ history argument-dependent-lookup

9
推荐指数
3
解决办法
1207
查看次数

可以将重载运算符重构为非成员函数会破坏任何代码吗?

考虑重载加法运算的遗留类模板+=+

template<class T>
class X
{
public:
    X() = default;
    /* implicict */ X(T v): val(v) {}

    X<T>& operator+=(X<T> const& rhs)       { val += rhs.val; return *this; }
    X<T>  operator+ (X<T> const& rhs) const { return X<T>(*this) += rhs;    } 

private:
    T val;
};
Run Code Online (Sandbox Code Playgroud)

在代码审查时,观察到它+是可实现的+=,为什么不使它成为非成员(并保证左右参数的对称性)?

template<class T>
class X
{
public:
    X() = default;
    /* implicit */ X(T v): val(v) {}

    X<T>& operator+=(X<T> const& rhs)       { val += rhs.val; return *this; }

private: …
Run Code Online (Sandbox Code Playgroud)

c++ operator-overloading implicit-conversion argument-dependent-lookup non-member-functions

9
推荐指数
1
解决办法
208
查看次数

对于类型为类模板特化的参数,ADL背后的基本原理是什么?

我花了一些时间试图意识到为什么我的代码不能编译,我已经意识到在C++ Argument Dependent Lookup中使用模板typename参数来确定名称查找范围.

#include <string>
#include <functional>

namespace myns {

    template<typename T>
    struct X
    {};

    template<typename T>
    auto ref(T) -> void
    {}

} // namespace myns

auto main() -> int
{
    ref(myns::X<int>{});
    ref(myns::X<std::string>{}); // error: call to 'ref' is ambiguous
}
Run Code Online (Sandbox Code Playgroud)

所以前面的ref调用编译,因为myns::X<int>myns::ref考虑,而后者不编译,因为它发现myns::ref()以及std::ref

我的问题是这有用吗?我为什么需要这个?你有什么想法,例子吗?现在我只能看到上面例子中的缺点,它会引入不必要的歧义.

c++ templates argument-dependent-lookup

9
推荐指数
1
解决办法
184
查看次数

条件noexcept和重载的不一致

我有一个与问题非常相似的问题.

简而言之,我有一个magic方法,noexcept如果是另一种方法noexcept.

奇怪的是,这个"另一个方法"有两个重载,编译器选择第二个重载来确定magic noexcept-ness.

但是,当magic稍后调用时,会调用第一个重载,但是noexcept-ness magic仍然保持不变!

这是wandbox 链接

据我所知:

  1. noexcept(magic(dummy2{})) 电话
  2. noexcept(noexcept(adl_caller(...)) 这可以追溯到
  3. adl_caller(..., priority_tag<0>) noexcept因为user_method(dummy2)此时编译器不知道.

然而,相当公平,如何user_method(dummy2)称为3行以上?这是标准的意图吗?

对不起,如果我不够清楚的话.

#include <iostream>

template <unsigned N> struct priority_tag : priority_tag<N - 1> {};
template <> struct priority_tag<0> {};

template <typename T>
auto adl_caller(T t, priority_tag<1>) noexcept(noexcept(user_method(t)))
    -> decltype(user_method(t)) {
  std::cout << "first adl_caller overload" << std::endl;
  user_method(t);
}

// …
Run Code Online (Sandbox Code Playgroud)

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

9
推荐指数
1
解决办法
339
查看次数