标签: overload-resolution

使用双花​​括号进行向量初始化:std::string 与 int

在这个问题的回答中:用双花括号初始化向量<string>

结果表明

vector<string> v = {{"a", "b"}};
Run Code Online (Sandbox Code Playgroud)

将使用一个元素std::vector调用构造函数。因此向量中的第一个(也是唯一的)元素将由 构造。这会导致未定义的行为,但这超出了这里的重点。initializer_list{"a", "b"}

我发现的是

std::vector<int> v = {{2, 3}};
Run Code Online (Sandbox Code Playgroud)

std::vector使用两个元素initializer_list中的一个调用构造函数。

为什么会出现这种行为差异的原因呢?

c++ initializer-list overload-resolution c++14

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

重载 noexcept 难道没有意义吗?

我试图了解 noexcept 功能。我知道这可能会令人困惑,但除此之外,如果可能的话,不能从调用函数中推导出来。

这是这种情况的非工作示例,

void f(){}
void f() noexcept{} // not allowed in c++

void g(){f();} // should call f
void h() noexcept{f();} // should call f noexcept
int main(){
    g();
    h();
}
Run Code Online (Sandbox Code Playgroud)

如果调用函数 ( h) 中没有 try/catch 块,那么编译器可以推断出有人对调用特定的 f 感兴趣。

此模式是否以其他解决方法形式使用?

我所能想象的就是这样的东西,但它不是很通用:

template<bool NE> void F() noexcept(NE);

template<>
void F<true>() noexcept(true){}
template<>
void F<false>() noexcept(false){}

void g(){F<noexcept(g)>();} // calls F<false>
void h() noexcept{F<noexcept(h)>();} // call F<true>
Run Code Online (Sandbox Code Playgroud)

有些人可能想知道为什么这会有意义。我的逻辑是,C++ 允许重载const函数参数和成员函数。 const例如,成员函数更喜欢调用const成员重载。

我认为noexcept函数调用noexcept …

overloading overload-resolution noexcept c++11 c++17

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

如何解释这个“调用不明确”的错误?

问题

考虑这两个扩展方法,它们只是从任何类型T1到的简单映射T2,加上一个重载以流畅地映射到Task<T>

public static class Ext {
    public static T2 Map<T1, T2>(this T1 x, Func<T1, T2> f)
       => f(x);
    public static async Task<T2> Map<T1, T2>(this Task<T1> x, Func<T1, T2> f)
        => (await x).Map(f);
}
Run Code Online (Sandbox Code Playgroud)

现在,当我使用第二个重载映射到引用类型时......

var a = Task
    .FromResult("foo")
    .Map(x => $"hello {x}"); // ERROR

var b = Task
    .FromResult(1)
    .Map(x => x.ToString()); // ERROR
Run Code Online (Sandbox Code Playgroud)

...我收到以下错误:

CS0121:以下方法或属性之间的调用不明确:“Ext.Map(T1, Func)”和“Ext.Map(Task, Func)”

映射到值类型工作正常:

var c = Task
    .FromResult(1)
    .Map(x => x + 1); // works

var …
Run Code Online (Sandbox Code Playgroud)

c# generics overload-resolution

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

数组到指针的转换 + rvalue-ref:重载分辨率差异 GCC vs clang

#include <iostream>
#define FUNC() { std::cout << __PRETTY_FUNCTION__ << "\n"; }

void foo(char const*&&   ) FUNC() // A
void foo(char const(&)[4]) FUNC() // B

int main()
{
    foo("bar");
}
Run Code Online (Sandbox Code Playgroud)

演示

当在第一个重载 (A) 的参数类型中使用右值引用时,clang current master 明确地选择重载 A 而不是 B。另一方面,GCC current master 抱怨歧义。

我很惊讶字符串文字是4char const左值[expr.prim.literal]/1 , [lex.string]/6)应该更喜欢重载 A 上的数组到指针转换而不是身份转换过载 B.

如果没有右值引用,即void foo(char const*),GCC 和 clang 都拒绝调用不明确。这也是我不完全理解的事情,因为我会猜测仍然存在数组到指针的转换,因此[over.ics.rank]p3.2.1适用:

  • 标准转换序列 S1 是比标准转换序列 S2 更好的转换序列,如果

    • (3.2.1) S1是S2的真子序列(比较[over.ics.scs]定义的规范形式的转换序列,不包括任何左值转换;恒等转换序列被认为是任何非-身份转换序列),或者,如果不是,

在这两种情况下发生了什么?

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

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

当同样好的转换函数可用时,为什么重载决议更喜欢移动构造函数而不是非特殊构造函数?

以下程序:

#include <iostream>

struct A 
{ 
  A() { std::cout << "A()\n"; }
  A(int) { std::cout << "A(int)\n"; }
};

struct C {
  operator int() {
    std::cout << "operator int\n";
    return 42;
  }
  operator A() {
    std::cout << "operator A\n";
    return A();
  }
};

int main() {
    auto a = A{C{}};
};
Run Code Online (Sandbox Code Playgroud)

编译并在运行时打印:

operator A
A()
Run Code Online (Sandbox Code Playgroud)

请参阅Godbolt 链接

这表明选择了 的移动构造函数A来执行初始化,C::operator A()并被调用以转换C为移动构造函数期望的类型。

或者,A::A(int)构造函数可能已被选中C::operator int()并被调用。但A::A(int)显然失去了重载分辨率。

为什么会发生这种情况?我无法在标准中看到任何解释为什么移动构造函数A赢得重载决议的规则。

(这个问题受到 …

c++ overload-resolution c++17

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

C++ 中的重载函数和多个转换运算符歧义,编译器不同意

在下面的程序中 structS提供了两个转换运算符: indouble和 in long long int。然后一个类型的对象S被传递给一个函数f,重载为floatand double

struct S {
    operator double() { return 3; }
    operator long long int() { return 4; }
};

void f( double ) {}
void f( float ) {}

int main() {
    S s;
    f( s );
}
Run Code Online (Sandbox Code Playgroud)

MSVC 编译器可以正常接受程序,并选择f( double )重载。f然而,GCC 和 Clang 都发现, demo的调用存在歧义:https: //gcc.godbolt.org/z/5csd5dfYz

看来MSVC在这里是对的,因为转换: operator long long int()->f( float )不是提升。这是错的吗? …

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

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

继承类并重用其构造函数问题在基类中缺失

在下面的程序中,struct B有两个用户定义的构造函数:一个来自int,另一个来自int&&(显然这不太实用)。并且 的对象B是从左值创建的,它应该明确选择第一个构造函数。thenstruct CB通过 - 声明继承其构造函数而派生的using,并且 的对象C是从完全相同的左值创建的:

struct B {
    B(int) {}
    B(int&&) {}
};

int i = 1;
B b(i); //ok everywhere

struct C : B {
    using B::B;
};

C c(i); //ok in Clang only
Run Code Online (Sandbox Code Playgroud)

MSVC 在最后一行打印出相当奇怪的错误:

source>(10): error C2668: 'B::B': ambiguous call to overloaded function
<source>(3): note: could be 'B::B(int &&)'
<source>(2): note: or       'B::B(int)'
<source>(10): note: while trying to match …
Run Code Online (Sandbox Code Playgroud)

c++ using language-lawyer overload-resolution

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

C++ 中构造函数和继承构造函数之间的重载解析 - 哪个编译器是正确的?

在下面的程序中,从其基类struct B继承已删除的构造函数,并且还定义了附加构造函数。然后创建一个对象:B(int)AB(int&&)BB b(1)

struct A {
    A() {}
    A(int) = delete;
};

struct B : A {
    using A::A;
    B(int&&) {}
};

int main() {
    B b(1);
}
Run Code Online (Sandbox Code Playgroud)

如果构造函数B(int)B(int&&)都直接在结果中定义,B则构造函数选择会产生歧义。在这个例子中,GCC 打印了一个

重载“B(int)”的调用不明确`

错误也是如此。

但 Clang 更喜欢在 中声明的构造函数B而不是从 继承的构造函数A。演示: https: //gcc.godbolt.org/z/dnErEenE5

这里是哪个编译器?

c++ language-lawyer overload-resolution

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

SFINAE 不适用于递归函数

让我们创建柯里化函数。

template <typename TFunc, typename TArg>
class CurryT
{
public:
    CurryT(const TFunc &func, const TArg &arg)
      : func(func), arg(arg )
        {}

    template <typename... TArgs>
        decltype(auto) operator()(TArgs ...args) const
            { return func(arg, args...); }

private:
    TFunc func;
    TArg  arg ;
};

template <typename TFunc, typename TArg>
    CurryT<decay_t<TFunc>, remove_cv_t<TArg>>
        Curry(const TFunc &func, const TArg &arg)
            { return {func, arg}; }
Run Code Online (Sandbox Code Playgroud)

以及将函数解耦为单参数函数的函数:

// If single argument function (F(int)).
template <typename F>
    static auto Decouple(const F &f, enable_if_t<is_invocable_v<F, int>> * = nullptr) …
Run Code Online (Sandbox Code Playgroud)

c++ recursion templates sfinae overload-resolution

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

接受 const char(&amp;)[N] 的函数模板是否比接受 const T&amp; 的函数模板更专业?

我定义了两个版本的函数模板,名为compare

\n
#include <cstring>\n\nusing namespace std;\n\n// fist version\ntemplate <size_t N, size_t M>\nint compare(const char (&a)[N], const char (&b)[M]) {\n    return strcmp(a, b);\n}\n\n// second version\ntemplate <typename T>\nint compare(const T &a, const T &b) {\n    if (a < b) return -1;\n    if (b < a) return 1;\n    return 0;\n}\n\nint main() {\n    const char *p1 = "dog", *p2 = "cat";\n    compare(p1, p2); // call second version\n    compare("dog", "cat"); // call second version?\n\n    return 0;\n}\n
Run Code Online (Sandbox Code Playgroud)\n

在使用c++11std的CPP Primer(第5版)一书中,作者说compare(p1, p2)将调用第二版模板,因为没有办法将指针转换为对数组的引用。将 …

c++ function-templates overload-resolution compiler-bug

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