标签: argument-dependent-lookup

Koenig Lookup的奇怪行为

考虑以下计划:

    namespace NS2 {
      class base { };

      template<typename T>
      int size(T& t) {
        std::cout << "size NS2 called!" << std::endl;
        return sizeof(t);
      } 
    };

    namespace NS1 {
      class X : NS2::base { };
    }

    namespace NS3 {
      template<typename T>
      int size(T& t) {
        std::cout << "size NS3 called!" << std::endl;
        return sizeof(t) + 1;
      }

      template<typename T>
      class tmpl 
      {
      public:
        void operator()() { size(*this); }
      };
    };

int main() +{
  NS3::tmpl<NS1::X> t;
  t();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

我的编译器(gcc 4.3.3)不编译程序,因为对size的调用是不明确的.名称空间NS2似乎被添加到类tmpl中的size调用的关联名称空间集合中.即使在阅读了ISI标准中有关Koenig …

c++ templates g++ argument-dependent-lookup

3
推荐指数
1
解决办法
369
查看次数

为什么编译器找不到这个运算符<< overload?

我正在尝试为operator<<标准库容器的特定实例化编写重载,这些容器将存储在boost::variant.这是一个说明问题的小例子:

#include <iostream>
#include <vector>

std::ostream & operator<<( std::ostream & os, const std::vector< int > & ) {
  os << "Streaming out std::vector< int >";
  return os;
}

std::ostream & operator<<( std::ostream & os, const std::vector< double > & ) {
  os << "Streaming out std::vector< double >";
  return os;
}

#include <boost/variant.hpp>

typedef boost::variant< std::vector< int >, std::vector< double > > MyVariant;

int main( int argc, char * argv[] ) {
  std::cout << MyVariant();
  return …
Run Code Online (Sandbox Code Playgroud)

c++ boost operator-overloading variant argument-dependent-lookup

3
推荐指数
1
解决办法
1511
查看次数

ADL在构造函数初始化列表中

如何在构造函数初始化列表中启用ADL?例如,假设我有一个bignum具有命名空间级abs功能.现在我想编写一个类Foo,用传递给构造函数的实例的绝对值初始化其成员; 它应该使用命名空间级别,abs如果它存在,std::abs否则:

template<typename T>
struct Foo
{
    T _data;

    Foo(T data):
        _data(abs(data)) // I want find abs with ADL here
    {}
};
Run Code Online (Sandbox Code Playgroud)

无论如何,在类范围内禁止使用声明,我不想"污染"命名空间.如何启用ADL以使其在构造函​​数初始化列表中工作?

c++ initialization-list argument-dependent-lookup c++11

3
推荐指数
1
解决办法
258
查看次数

为什么功能乐趣不适合ADL?

我有简单namespace,它有一个变量和一个函数.在main我尝试调用没有名称空间限定符的函数,并使用名称空间限定符调用变量.

namespace SAM
{
    int p = 10;
    void fun(int)
    {
        cout<<"Fun gets called";
    }
} 

int main()
{

    fun(SAM::p);//why SAM::fun is not get called?
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我不能称之为有趣,为什么它不符合ADL(依赖于参数的名称查找)?

我在Visual Studio中遇到以下错误.

'有趣':找不到标识符

如果我使用SAM::fun它,它的工作原理.

c++ visual-c++ argument-dependent-lookup

3
推荐指数
1
解决办法
70
查看次数

在不创建参数对象的情况下解析constexpr函数

精简版:

如果我有这样的功能:

constexpr bool has_some_property(Foo) { return true; }
Run Code Online (Sandbox Code Playgroud)

有没有办法调用函数而不必实际实例化Foo?如果Foo不是默认可构造的话?

长卷版本:

安东尼威廉姆斯最近写了一篇文章,详细介绍了一套为任何enum class专门用于特定模板的对象启用的免费功能.它遵循类似的方案中<ios>,std::is_error_code其中一个专门用于用户定义的类型或值的模板,以允许enable_if启用某些功能.在Anthony的案例中:

template<>
struct enable_bitmask_operators<my_bitmask>{
    static constexpr bool enable=true;
};
Run Code Online (Sandbox Code Playgroud)

然后在定义运算符时:

template<typename E>
typename std::enable_if<enable_bitmask_operators<E>::enable,E>::type
operator|(E lhs,E rhs){
Run Code Online (Sandbox Code Playgroud)

此技术的问题是模板特化必须与原始模板位于同一名称空间中,因此这不起作用:

namespace mystuff {
    enum class Foo {
        ...
    };

    // Fail: wrong namespace
    template<>
    struct enable_bitmask_operators<Foo> : std::true_type {}
Run Code Online (Sandbox Code Playgroud)

另一种方法是使用一个constexpr函数,该函数可以在与类相同的命名空间中解析:

namespace mystuff {
    enum class Foo {
        ...
    };
    constexpr bool enable_bitmask_operators(Foo) { return …
Run Code Online (Sandbox Code Playgroud)

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

3
推荐指数
1
解决办法
648
查看次数

为什么Koening查找不能在这里工作?

依赖于参数的查找说:

对于类类型的参数(包括union),该集合包含... a)类本身b)...

那为什么printX找不到X?

 #include<iostream>
using namespace std;

class A {
public:
    static const int X = 1;
};

class B {
public:
    static void printX(A a)
    {
        cout << "X is " << X << endl;
    }
};

int main(int argc, char** argv)
{
    A a;
    B::printX(a);
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c++ argument-dependent-lookup

3
推荐指数
1
解决办法
73
查看次数

在类(模板)成员函数体内进行ADL查找

struct B {};
struct C : B {};
void f(B){} // worse match than A::f<C>

struct A {
    template<class T>
    void f(T v) {
        f(v); // #1
    }
};

int main()
{
    A{}.f(C{});
}
Run Code Online (Sandbox Code Playgroud)

在线激活ADL查找#1非常简单

{
    using ::f;
    f(v);
}
Run Code Online (Sandbox Code Playgroud)

我认为在没有using指令的情况下使代码失败的规则是:

[basic.lookup.argdep]/3设X是非限定查找生成的查找集,让Y为参数相关查找生成的查找集(定义如下).如果X包含

  • (3.1)集体成员的声明,或
  • (3.2)不是使用声明的块范围函数声明,或
  • (3.3)既不是函数也不是函数模板的声明

那么Y是空的.[...]

因此,由于f非ADL查找找到的调用将找到A::f,这是一个类成员,ADL-lookup发现的重载将被丢弃.

哪个C++规则允许忽略3.1中的限制using声明,以使上面的代码编译?

我想我完全误解了必须应用规则[basic.lookup.argdep]/3的上下文,或者在理解名称查找过程中我可能有一个更大的隐藏漏洞.

c++ language-lawyer class-members argument-dependent-lookup c++17

3
推荐指数
1
解决办法
168
查看次数

为什么ADL无法与未命名的initializer_list一起使用?

考虑以下代码。在这里,如果我们std::begininitializer_list显式使用未命名std::,则可以正常工作。如果我们省略了std::begin在named上使用initializer_list,它也可以正常工作。但是,如果我们std::与第一种情况类似并省略其余部分,则它将无法编译。

#include <iostream>
#include <iterator>
void func(int len, const int* x)
{
    for(int i=0;i<len;++i)
        std::cout << x[i] << "\n";
}
int main()
{
    {
        // OK
        func(5, std::begin({1,3,6,823,-35}));
    }
    {
        // OK
        auto&& list = {1,3,6,823,-35};
        func(5, begin(list));
    }
//  {
//      // Fails to compile
//      func(5, begin({1,3,6,823,-35}));
//  }
}
Run Code Online (Sandbox Code Playgroud)

我收到以下编译错误(在取消注释错误代码后):

test.cpp: In function ‘int main()’:
test.cpp:21:11: error: ‘begin’ was not declared in this …
Run Code Online (Sandbox Code Playgroud)

c++ initializer-list argument-dependent-lookup c++11

3
推荐指数
1
解决办法
52
查看次数

如何防止 ADL 期间出现阴影?

假设我有一个扩展(STL)容器的类并提供了一个习惯的begin成员函数:

#include <vector>

template <typename Cont>
struct Bar {
    Cont c;
    auto my_begin() { return begin(c); }
};

int main() {
    Bar<std::vector<int>> b;
    b.my_begin();
}
Run Code Online (Sandbox Code Playgroud)

通过ADL,我不必std::begin()调用前指定。这很好,因为std::begin(v)总是尝试调用v.begin(),用户可能想要使用没有.begin()接口的自定义容器,因此如果他定义了自己的自由函数begin(v)Bar就会使用它。但是,如果我也重命名my_begin为ADL,似乎 ADL 将不再起作用begin,就好像它被掩盖了一样。编译器只会抱怨它在类范围内找不到匹配的调用:

prog.cc: In instantiation of 'auto Bar<Cont>::begin() [with Cont = std::vector<int>]':
prog.cc:11:13:   required from here
prog.cc:6:27: error: use of 'auto Bar<Cont>::begin() [with Cont = std::vector<int>]' before deduction of 'auto'
    6 |     auto begin() …
Run Code Online (Sandbox Code Playgroud)

c++ templates argument-dependent-lookup

3
推荐指数
1
解决办法
68
查看次数

警告由于 ADL 导致丢失 std:: 前缀

当参数类型位于命名空间中时,可以省略sstd::的命名空间(通常是这种情况)。<algorithm>是否有任何警告或整齐的规则可以发现此类遗漏?

#include <vector>
#include <algorithm>

std::vector<int> v;
for_each(v.begin(), v.end(), [](auto){});
return 0;
Run Code Online (Sandbox Code Playgroud)

上面的示例使用最新的 clang 和 -Wall、-Wextra 和 -Wpedantic 编译,不会发出任何诊断信息:

https://godbolt.org/z/dTsKbbEKe

c++ compiler-warnings argument-dependent-lookup clang-tidy

3
推荐指数
1
解决办法
259
查看次数