标签: overload-resolution

C++ 0x与使用声明混淆

这种情况会发生什么:

struct A {
  void f();
};

struct B : virtual A {
  using A::f;
};

struct C : virtual A {
  using A::f;
};

struct D : B, C { 
  void g() {
    f();
  }
};
Run Code Online (Sandbox Code Playgroud)

感兴趣的是 f().显然,f根据10.2FDIS 的查找成功并找到A::f.但是,哪些候选人会考虑重载决议?规范说13.3.1p4:

对于由using声明引入到派生类中的非转换函数,该函数被认为是派生类的成员,用于定义隐式对象参数的类型.

这样做的目的是使单个类,如果这样一类同时包含自己的成员函数和using声明带来的基类函数的名称为范围,即重载解析过程中的所有功能,考生在他们的隐含对象是相同类型参数.但这对于上面的例子意味着什么呢?候选人是否会如下?

void F1(B&)
void F2(C&)
// call arguments: (lvalue D)
Run Code Online (Sandbox Code Playgroud)

这似乎是错误的,因为根据我们在查找结果集中只有一个声明10.2p7.我们该如何解读?

c++ using-declaration overload-resolution c++11

15
推荐指数
1
解决办法
685
查看次数

Java:运行时方法解析

我正在通过解释器进行一些动态的代码调用,而我正在进入JLS第15.12节中讨论的方法解决的粘性丑陋区域.

选择方法的"简单"方法是,当您知道所有参数的确切类型时,您可以使用该方法Class.getDeclaredMethod(String name, Class[] parameterTypes).也许您必须检查方法可访问性和类的超类/超级接口.

但这并不包括以下任何一种情况,所以它有点无用:

  • 装箱/拆箱原语
  • 亚型
  • 可变参数
  • 一个null参数(可以是任何类型,除非解释器另有说明;在编译时,任何歧义都会通过将null转换为类/接口来消除)
  • 原始类型转换(不是Java的一部分,但在语言环境中是允许的 - 例如Rhino Javascript,其中所有数字都是浮点数,因此Java代码可能需要一个int但调用者传入的数字是a int或a double)

(见下面的前三个快速示例)

所以现在我必须编写自己的方法解析库...

有没有任何着名的框架库来协助这个?

package com.example.test.reflect;

import java.lang.reflect.Method;

public class MethodResolutionTest {
    public void compute(int i)              { /* implementation... */ }
    public void compute(Long l)             { /* implementation... */ }
    public void compute(Object obj)         { /* implementation... */ }
    public void compute(String... strings)  { /* implementation... */ }

    public static void main(String[] args) {
        Class<?> cl = …
Run Code Online (Sandbox Code Playgroud)

java reflection overload-resolution

15
推荐指数
1
解决办法
2059
查看次数

如何检查给定呼叫站点的重载决策集

如何检查过载分辨率设置?

我在多个呼叫站点中使用了4个竞争功能.在一个调用站点中,我期望调用一个函数,但编译器会选择另一个函数.我不知道为什么/它不是微不足道的.要了解正在发生的事情,我正在使用enable_if/disable_if打开/关闭功能,但这实在是很慢/乏味/烦人.

所以我希望编译器告诉我"为什么?".也就是说,对于这个单一呼叫站点:

  • ADL发现的所有功能,
  • 重载决策集中的所有函数,
  • 从重载决策集中拒绝的所有函数以及它们被拒绝的原因,以及
  • 重载决策集中的函数行列以及它们的排名原因.

不需要有关访问控制的信息.

基本上我希望用一个#pragma或类似的(__builtin...)标记呼叫站点.但libclang也是一种选择.

我可以访问tip-of-trunk clang和gcc,但如果需要可以安装其他编译器/工具.

c++ debugging gcc clang overload-resolution

15
推荐指数
1
解决办法
736
查看次数

C#lambda表达式的参数类型推断中的歧义

我的问题是由Eric Lippert的博客文章推动的.请考虑以下代码:

using System;
class Program {
    class A {}
    class B {}
    static void M(A x, B y) { Console.WriteLine("M(A, B)"); }
    static void Call(Action<A> f) { f(new A()); }
    static void Call(Action<B> f) { f(new B()); }
    static void Main() { Call(x => Call(y => M(x, y))); }
}
Run Code Online (Sandbox Code Playgroud)

这种成功并打印编译M(A, B),因为编译器计算出该类型的xy在lambda表达式应该是AB分别.现在,添加一个重载Program.M:

using System;
class Program {
    class A {}
    class B {}
    static void …
Run Code Online (Sandbox Code Playgroud)

c# lambda overload-resolution

15
推荐指数
1
解决办法
435
查看次数

"std :: cout << std :: endl;"怎么样?编译?

大多数IO流操纵器都是具有以下签名的常规函数​​:

std::ios_base& func( std::ios_base& str );
Run Code Online (Sandbox Code Playgroud)

但是,一些操纵器(包括最常用的操纵器 - std::endlstd::flush)是以下形式的模板:

template< class CharT, class Traits >
std::basic_ostream<CharT, Traits>& func(std::basic_ostream<CharT, Traits>& os);
Run Code Online (Sandbox Code Playgroud)

然后,如果std::cout << std::endl;以下示例失败,如何编译成功:

$ cat main.cpp 
#include <iostream>

int main()
{
    auto myendl = std::endl;
    std::cout << myendl;
}

$ g++ -std=c++11    main.cpp   -o main
main.cpp: In function ‘int main()’:
main.cpp:5:24: error: unable to deduce ‘auto’ from ‘std::endl’
     auto myendl = std::endl;
                        ^
Run Code Online (Sandbox Code Playgroud)

很明显,上下文(in std::cout << std::endl;)有助于编译器消除对引用的歧义std::endl.但是,管理该程序的规则是什么?对于重载分辨率来说,这似乎是一个真正的挑战,它必须同时回答两个问题:

  1. 哪个专业std::endl<CharT, Traits>() …

c++ templates overload-resolution iomanip

15
推荐指数
3
解决办法
1961
查看次数

C++ 中具有多个参数包的函数的重载解析

一个 C++ 函数可以有多个参数包。虽然看起来不太实用,但了解它们的语言规则仍然很有趣。

例如,如果有两个重载:

constexpr int f(auto...) { return 1; }
constexpr int f(auto..., auto...) { return 2; }
Run Code Online (Sandbox Code Playgroud)

f不带参数的调用f()在 MSVC 中选择版本 1,在 Clang 中选择版本 2,ambiguous overloaded call在 GCC 中选择版本 2。

如果f使用参数调用f(1),则 MSVC 和 GCC 都选择版本 1,而 Clang 仍选择版本 2。

演示: https: //gcc.godbolt.org/z/PWr6h1dn1

这里是哪个编译器?

有一个类似的问题带有两个参数包的函数模板重载解析,但是

  • 那里的函数只有一个参数包作为函数参数(第二个参数包根本没有使用),
  • 该示例会导致所有测试的编译器中出现歧义错误(但是提到的编译器错误仍未解决)。实际上,在此示例中也可能出现歧义,但这里大多数编译器选择其中一个重载而不会出现错误。

c++ language-lawyer overload-resolution c++20 parameter-pack

15
推荐指数
1
解决办法
333
查看次数

为什么C#编译器重载解析算法将具有相同签名的静态和实例成员视为相等?

让我们有两个成员相同的签名,但一个是静态的而另一个是 - 不是:

class Foo
{
    public void Test() { Console.WriteLine("instance"); }

    public static void Test() { Console.WriteLine("static"); }
}
Run Code Online (Sandbox Code Playgroud)

但是这样的代码生成会带来编译错误:

类型'Foo'已经定义了一个名为'Test'的成员,它具有相同的参数类型

但为什么?

让我们成功编译,然后:

  • Foo.Test() 应输出"静态"

  • new Foo().Test();应该输出"实例"

无法调用静态成员而不是实例1,因为在这种情况下会出现另一个更合理的编译器错误:

无法使用实例引用访问成员'Foo.Test()'; 用类型名称来限定它

.net c# static-members overload-resolution

14
推荐指数
1
解决办法
451
查看次数

在此示例中,赋值运算符重载解析如何工作?结果对我来说意外

这是我不理解的代码:

class Base
{
public:
    Base(){}

    Base operator=(Base ob2)
    {
        std::cout << "Using Base operator=() " << '\n';
        return *this;
    }
};

class Derived : public Base
{
public:
    Derived(){}
    Derived operator=(Base ob2)
    {
        std::cout << "Using Derived operator=() " << '\n';
        return *this;
    }
};

int main()
{
    Derived derived1, derived2;
    Base base1;

    derived1 = derived2;  // Uses base operator=()

    derived1 = base1;  // Uses derived operator=()

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

确定的第一个赋值使用Base类的运算符,第二个赋值使用Derived类的运算符的语言规则是什么?

是的,我知道通常不会像这样声明赋值运算符.这就是为什么我称它为accademical.

c++ operator-overloading overload-resolution

14
推荐指数
1
解决办法
3083
查看次数

SFINAE远离复制构造函数

在某些条件下,我想要SFINAE远离类模板的复制构造函数和复制赋值运算符.但是如果我这样做,则会生成默认的复制构造函数和默认赋值运算符.SFINAE基于我作为类模板参数传递的标签完成.问题是,SFINAE仅适用于模板,复制构造函数/赋值运算符不能作为模板.是否存在变通方法?

c++ templates copy-constructor sfinae overload-resolution

14
推荐指数
2
解决办法
902
查看次数

重载转换函数模板

考虑以下:

struct X {
    template <class T> operator T();  // #1
    template <class T> operator T&(); // #2
};

int        a = X{}; // error: ambiguous
int&       b = X{}; // calls #2
int const& c = X{}; // calls #2
Run Code Online (Sandbox Code Playgroud)

这种情况b很简单,#2是唯一可行的候选人.表示初始化的#2首选规则是什么,但两者对于初始化是不明确的?#1int const&int

c++ conversion-operator language-lawyer overload-resolution

14
推荐指数
1
解决办法
114
查看次数