标签: argument-dependent-lookup

确定"通用函数"的返回类型

假设,我想开发一个通用库,它应该可以用于类似数字的类型,包括双重和用户定义的类型.我现在面临的问题是,我不知道如何编写函数模板的返回类型,就像这样:

template<class T>
auto transmogrify(T x)
-> ???
{
    using std::abs;
    return abs(x)+2.0;
}
Run Code Online (Sandbox Code Playgroud)

using声明使这个函数模板的主体适用于原始类型,因为它们没有关联的命名空间(因此没有ADL).但是我希望transmogrify使用专门的abs函数,以防用户定义类型的作者提供自己的abs函数.我不能简单地使用

-> decltype( abs(x)+2.0 )
Run Code Online (Sandbox Code Playgroud)

因为这不适用于比赛,因为std :: abs不在范围内(据我所知).但写作

-> decltype( std::abs(x)+2.0 )
Run Code Online (Sandbox Code Playgroud)

会禁用ADL.但禁用ADL不是一种选择.此外,专用abs函数返回的值可能不是T类型,而是某些其他类型.

关于如何解决返回类型问题的任何想法,同时(a)保持ADL和(b)回退到某些默认函数(如本例中的std :: abs),对于不提供专用abs的类型.

c++ generic-programming decltype argument-dependent-lookup c++11

5
推荐指数
1
解决办法
295
查看次数

理解C++中的运算符范围

#include <iostream>

namespace Foo
{
    class Baz { };   

    std::ostream& operator<< ( std::ostream& ostream , const Baz& baz )
    {
        return ostream << "operator<<\n";
    }
}

int main()
{
    std::cout << Foo::Baz();
}
Run Code Online (Sandbox Code Playgroud)

operator<<Foo命名空间中定义了一个.为什么可以从全球范围调用它?

c++ scope namespaces function argument-dependent-lookup

5
推荐指数
1
解决办法
166
查看次数

在具有相同名称的成员函数的情况下的ADL

情况是某些成员函数bar::Bar::frobnicate想要利用ADL从具有相同名称的函数内的某个未知命名空间中查找函数.但是,它只找到自己的名字.

测试用例

(请注意,实际上,这Bar是一个Foo不可知的模板;这只是可重现的,最小的测试用例)

namespace foo {
    struct Foo {};
    void frobnicate(Foo const &) {}
}

namespace bar {
    struct Bar {
        void frobnicate() {
            foo::Foo foo;
            frobnicate(foo); // <-- error
        }
    };
}

int main () {
    bar::Bar x;
    x.frobnicate();
    frobnicate(foo::Foo());
}
Run Code Online (Sandbox Code Playgroud)

结果是:

test.cc: In member function ‘void bar::Bar::frobnicate()’:
test.cc:10:31: error: no matching function for call to ‘bar::Bar::frobnicate(foo::Foo&)’
test.cc:10:31: note: candidate is:
test.cc:8:18: note: void bar::Bar::frobnicate()
test.cc:8:18: note:   candidate expects 0 arguments, …
Run Code Online (Sandbox Code Playgroud)

c++ interface argument-dependent-lookup non-member-functions

5
推荐指数
1
解决办法
381
查看次数

超载左移操作员

我已经研究过并发现当你想为cout重载输出流操作符时,那么正确的方法是这样做:

std::ostream& operator<<(std::ostream& os, const T& obj)
Run Code Online (Sandbox Code Playgroud)

这个函数必须在类之外定义,因为这里发生的是操作符<<实际上是ostream中定义的友元函数,你正在使用它.但是,问题是,这个函数究竟是如何在ostream中定义的?由于此函数需要2个参数,而第二个参数是用户定义的,因此他们无法猜出将要发生什么.

特定类的重载应如下所示:

std::ostream& operator<<(std::ostream& os, const MyClass& obj)
Run Code Online (Sandbox Code Playgroud)

编译器/库如何为第二个参数采用泛型定义,特别是因为在C++中没有泛型类(如Java中的Object)这样的东西?

c++ operator-overloading argument-dependent-lookup

5
推荐指数
1
解决办法
1万
查看次数

编译器如何在下面的代码中通过ADL找到模板函数X :: max(T const&,T const&)?

该标准的引用表示赞赏.

#include <iostream>

namespace X {
    class A {};
}

template <typename T>
inline T const& max(T const& a, T const& b, T const& c)
{
    return max(max(a, b), c);
}

inline X::A const& max(X::A const& a, X::A const& b)
{
    std::cout << "non-template" << '\n';
    return a;
}

int main()
{
    X::A a, b, c;
    max(a, b, c);
}

namespace X {
    template <typename T>
    inline T const& max(T const& a, T const& b)
    {
        std::cout << "template" << …
Run Code Online (Sandbox Code Playgroud)

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

5
推荐指数
1
解决办法
440
查看次数

为什么using指令不影响ADL?

我试图了解为什么以下代码无法编译:

namespace ns {
  struct S {};
}

namespace alleq {
  inline bool
  operator==(const ns::S &, const ns::S &)
  {
    return true;
  }
}

namespace ns {
  using namespace alleq;
  // using alleq::operator==; // Works if you uncomment this
}

ns::S a;

void
f()
{
  ::ns::operator==(a, a); // OK
  a == a;                 // Error: no match for 'operator=='
}
Run Code Online (Sandbox Code Playgroud)

函数的第一行f确实可以编译,这使我相信命名空间ns包含一个function operator==。但是,当我比较type的两个值时ns::Soperator==找不到此函数。相比之下,using声明确实可以按预期工作,并且允许ADL f查找第二行ns::operator==

我怀疑原因与使用指令应该使符号看起来像它出现在全局名称空间中有关::(因为这是名称空间alleq …

c++ namespaces argument-dependent-lookup

5
推荐指数
1
解决办法
275
查看次数

C++运算符重载和关联的命名空间

以下简化示例编译gcc并且Visual Studio,但是失败了clang!?

namespace N
{
    struct A {};

    template <typename T>
    double operator+ (T a, double d) {return d;}

    template <typename T>
    double operator+ (double d, T a) {return d;}
}

void test()
{
    N::A a;
    double x;

    double y = a + x;
    double z = x + a;
}
Run Code Online (Sandbox Code Playgroud)

在我看来,ADL可以找到模板operator+名称空间N.

为什么不clang同意?它是clang其他编译器中的错误吗?

这是来自clang 3.5.1的编译错误(在coliru上测试过),我不明白这里有什么问题......

10 : error: overloaded 'operator+' must have at least one parameter …
Run Code Online (Sandbox Code Playgroud)

c++ namespaces operator-overloading clang argument-dependent-lookup

5
推荐指数
1
解决办法
525
查看次数

当无关类型定义为别名时,调用函数是不明确的

阅读了一篇很棒的文章真实的故事:高效的包装我试着自己实现元组作为练习:

#include <type_traits>
#include <utility>
#include <functional>

template< std::size_t I, typename T >
struct tuple_leaf { T value; };

template< std::size_t I, typename T >
T & get(tuple_leaf< I, T > & leaf)
{ return leaf.value; }

template< typename Is, typename ...Ts >
struct tuple_base;

template< std::size_t ...Is, typename ...Ts >
struct tuple_base< std::index_sequence< Is... >, Ts... >
    : tuple_leaf< Is, Ts >...
{
    using tuple_base_t = tuple_base;
    template< typename ...Args, typename = std::enable_if_t< (sizeof...(Ts) == sizeof...(Args)) > …
Run Code Online (Sandbox Code Playgroud)

c++ overload-resolution argument-dependent-lookup c++11

5
推荐指数
1
解决办法
224
查看次数

朋友功能模板查找

根据标准,在类中声明和定义的友元函数只能由ADL查找.所以,我认为以下代码应该编译.

template<int M>
struct test{
    template<int N = 0>
    friend void foo(test){}
};

int main(){
    test<2> t;
    foo(t);// compile
    foo<1>(t);// error
}
Run Code Online (Sandbox Code Playgroud)

但是,gcc给出以下错误:

main.cpp: In function 'int main()':

main.cpp:10:5: error: 'foo' was not declared in this scope

     foo<1>(t);

     ^~~
Run Code Online (Sandbox Code Playgroud)

然后,我有三个问题.

  1. 应该template<int N> foo按照标准找到?
  2. 为什么foo发现foo<1>不是?
  3. 除了定义foo外部之外还有解决方法吗?

c++ friend-function function-templates argument-dependent-lookup

5
推荐指数
1
解决办法
96
查看次数

使用具有boost :: optional的相等运算符

我正在尝试为另一个命名空间中定义的类型T定义一个等于运算符,然后使用相等运算符optional<T>.在clang(Apple LLVM 9.1.0)上,此代码:

    namespace nsp {
        struct Foo {
        };
    }
    bool operator==(const nsp::Foo& a, const nsp::Foo& b);

    void foo() {
        optional<nsp::Foo> a = none;
        optional<nsp::Foo> b = none;
        if (a == b)
            ;
    }
Run Code Online (Sandbox Code Playgroud)

导致错误:

/usr/local/include/boost/optional/detail/optional_relops.hpp:29:34: error: invalid operands to binary expression ('const nsp::Foo' and 'const nsp::Foo')
{ return bool(x) && bool(y) ? *x == *y : bool(x) == bool(y); }
                      ~~ ^  ~~
MWE.cpp:40:19: note: in instantiation of function template specialization 'boost::operator==<what3words::engine::nsp::Foo>' requested here
            if (a …
Run Code Online (Sandbox Code Playgroud)

c++ boost argument-dependent-lookup

5
推荐指数
1
解决办法
486
查看次数