标签: overload-resolution

左值参数是否比通用引用更喜欢左值引用参数?

在使用通用引用的同时,我遇到了clang和gcc在重载决策上不一致的情况.

#include <iostream>

struct foo {};

template<typename T>
void bar(T&) { std::cout << "void bar(T&)\n"; }

template<typename T>
void bar(T&&) { std::cout << "void bar(T&&)\n"; }

int main()
{
    foo f;
    bar(f);  // ambiguous on gcc, ok on clang
}
Run Code Online (Sandbox Code Playgroud)

gcc报告上面的调用是模棱两可的.但是,clang选择T&重载并成功编译.

哪个编译器有问题,为什么?

编辑:
在VS2013预览中测试相同的代码,它同意clang; 除了Intellisense,这是在gcc的一方:-)

c++ overload-resolution c++11 universal-reference forwarding-reference

17
推荐指数
1
解决办法
360
查看次数

gcc和clang之间的重载分辨率差异涉及移动构造函数和'Derived(Base &&)'构造函数

GCC(使用4.9测试)接受以下测试用例:

struct Base {};

struct Derived : Base {
    Derived();
    explicit Derived(const Derived&);
    explicit Derived(Derived&&);
    explicit Derived(const Base&);
    Derived(Base&&);
};

Derived foo() {
  Derived result;
  return result;
}

int main() {
  Derived result = foo();
}
Run Code Online (Sandbox Code Playgroud)

Clang(使用3.5测试)拒绝它,并显示以下错误消息:

test.cpp:13:10: error: no matching constructor for initialization of 'Derived'
  return result;
         ^~~~~~
test.cpp:8:5: note: candidate constructor not viable: no known conversion from 'Derived' to 'Base &&' for 1st argument
    Derived(Base&&);
    ^
test.cpp:4:5: note: candidate constructor not viable: requires 0 arguments, but 1 was …
Run Code Online (Sandbox Code Playgroud)

c++ gcc clang overload-resolution c++11

17
推荐指数
1
解决办法
213
查看次数

使用空括号初始值设定项重载解析:指针或引用?

当我发现下面的代码输出"指针"时,我遇到了真实的WTF时刻.

#include <iostream>
#include <utility>

template<typename T>
struct bla
{
    static void f(const T*) { std::cout << "pointer\n"; }
    static void f(const T&) { std::cout << "reference\n"; }
};

int main()
{
    bla<std::pair<int,int>>::f({});
}
Run Code Online (Sandbox Code Playgroud)

std::pair<int,int>模板参数更改为int或任何其他基本类型,给(至少对我来说)预期的"模糊过载"错误.似乎内置类型在这里是特殊的,因为任何用户定义的类型(聚合,非平凡,具有默认构造函数等)都会导致调用指针超载.我相信模板不是重现它的必要条件,它只是让尝试不同类型变得简单.

就个人而言,我不认为这是合乎逻辑的,我认为在所有情况下都会出现模糊的重载错误,无论模板参数如何.GCC和Clang(我相信MSVC)在C++ 11/14/1z中都不同意我的观点.注意我完全知道这两个重载存在的错误API ,我保证不会写这样的东西.

所以问题就变成了:发生了什么?

c++ initializer-list overload-resolution c++11

17
推荐指数
1
解决办法
702
查看次数

如果尚未声明,为什么编译器会找到我的函数?

与我的期望相反,这个程序有效:

#include <iostream>


namespace a { struct item{}; }
namespace b { struct item{}; }


template<typename T>
void func(T t) { do_func(t); }


int main()
{    
    func(a::item{});
    func(b::item{});
}


namespace a { void do_func(item) { std::cout << "a::func\n"; } }
namespace b { void do_func(item) { std::cout << "b::func\n"; } }
Run Code Online (Sandbox Code Playgroud)

输出:

a::func
b::func
Run Code Online (Sandbox Code Playgroud)

在线编译器验证:

如果瞬间func<T>发生在身体main然后我会期待a::do_func并且b::do_func尚未宣布.

这怎么办?

更新

根据@Marc Claesen的说法,上述原因是:

在读取所有源之后执行模板实例化

但是,那么为什么这个代码并不能正常工作:

#include <iostream>

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

c++ overload-resolution

16
推荐指数
1
解决办法
270
查看次数

为什么编译器在这种重载决策情况下不能告诉更好的转换目标?(协方差)

理解关于重载解析的C#语言规范显然很难,现在我想知道为什么这个简单的情况失败了:

void Method(Func<string> f)
{
}
void Method(Func<object> f)
{
}
void Call()
{
    Method(() => { throw new NotSupportedException(); });
}
Run Code Online (Sandbox Code Playgroud)

这给出了编译时错误CS0121,以下方法或属性之间的调用是不明确的:后跟我的两个Method函数成员(重载).

我本来期望的是,Func<string>是一个更好的转换目标Func<object>,然后应使用第一个重载.

由于.NET 4和C#4(2010),通用委托类型Func<out TResult>协变TResult,并且由于该原因的隐式转换从存在Func<string>Func<object>同时明确的隐式转换可以从存在Func<object>Func<string>.那么它会产生Func<string>更好的转换目标,而重载分辨率应该选择第一个过载?

我的问题很简单:我在这里错过了C#规范的哪一部分?


增加:这很好用:

void Call()
{
    Method(null); // OK!
}
Run Code Online (Sandbox Code Playgroud)

c# delegates overloading covariance overload-resolution

16
推荐指数
1
解决办法
636
查看次数

SFINAE没有发生std :: underlying_type

使用clang 3.7.1,C++ 14可以很好地编译具有可变参数模板的SFINAE代码:

#include <array>
#include <iostream>
#include <vector>
#include <cstdint>

enum class Bar : uint8_t {
    ay, bee, see
};

struct S {

static void foo() {}

// std::begin(h) is defined for h of type H
template<typename H, typename... T>
static typename std::enable_if<std::is_pointer<decltype(std::begin(std::declval<H>()))*>::value>::type 
foo(const H&, T&&... t) 
{ std::cout << "container\n"; foo(std::forward<T>(t)...); }

// H is integral
template<typename H, typename... T>
static typename std::enable_if<std::is_integral<typename std::remove_reference<H>::type>::value>::type 
foo(const H&, T&&... t) 
{ std::cout << "integer\n"; foo(std::forward<T>(t)...); }

// H is an …
Run Code Online (Sandbox Code Playgroud)

c++ enums sfinae overload-resolution variadic-templates

16
推荐指数
1
解决办法
765
查看次数

使用`std :: enable_if`和非推导的上下文重载函数模板消歧

请考虑以下代码:

template <typename T>
struct dependent_type
{
    using type = T;
};

template <typename T>
auto foo(T) -> std::enable_if_t<std::is_same<T, int>{}>
{
    std::cout << "a\n"; 
}

template<typename T> 
void foo(typename dependent_type<T>::type) 
{
    std::cout << "b\n";
}
Run Code Online (Sandbox Code Playgroud)
  • 第一个重载foo可以T从其调用中推断出来.

  • 的第二过载foo是一个非推测的上下文.

int main()
{    
    foo<int>( 1 );      // prints "b"
    foo<double>( 1.0 ); // prints "b"
    foo( 1 );           // prints "a"
}
Run Code Online (Sandbox Code Playgroud)

为什么foo<int>( 1 )打印"b"而不是"a"?

wandbox示例

c++ templates language-lawyer overload-resolution c++14

16
推荐指数
1
解决办法
403
查看次数

字符串文字左值和右值引用的函数重载

test对于左值空字符串,左值非空字符串和右值字符串,下面的函数已重载。我尝试使用Clang和GCC进行编译,但在两种情况下都没有达到我期望的结果。

#include <iostream>

void test(const char (&)[1]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

template <unsigned long int N>
void test(const char (&)[N]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

void test(char*&&){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

int main(){
    char str1[] = "";
    char str2[] = "test";
    test("");
    test("test");
    test(str1);
    test(str2);
}
Run Code Online (Sandbox Code Playgroud)

使用clang 版本6.0.0-1ubuntu2的输出:

#include <iostream>

void test(const char (&)[1]){ std::cout << __PRETTY_FUNCTION__ << std::endl; }

template <unsigned long int N>
void test(const char (&)[N]){ std::cout << __PRETTY_FUNCTION__ << …
Run Code Online (Sandbox Code Playgroud)

c++ language-lawyer overload-resolution value-categories

16
推荐指数
1
解决办法
412
查看次数

C++ 中仅返回类型不同的重载函数模板

众所周知,仅返回类型不同的普通函数不能在 C++ 中重载。

但这个限制不适用于重载的函数模板,例如:

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

所有编译器都接受它,演示: https: //gcc.godbolt.org/z/qj73Mzehd

为什么该语言对模板做出这样的例外?

如果重载函数的返回类型不同,则可以使用强制转换为预期函数类型来选择其中一个函数。令人惊讶的是,即使返回类型实际上相同,Clang 也允许解决歧义,例如:

((int(*)(int))f)(3);
Run Code Online (Sandbox Code Playgroud)

选择

int f(auto) { return 1; }
Run Code Online (Sandbox Code Playgroud)

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

Clang这里错了吗?

c++ templates language-lawyer overload-resolution c++20

16
推荐指数
1
解决办法
1209
查看次数

为什么静态成员函数在重载解析期间被视为具有隐式对象参数?

在此链接中: 隐式对象参数

在这句话中:

如果任何候选函数是不具有显式对象参数 (C++23 起) 的成员函数(静态或非静态),但不是构造函数,则将其视为具有额外参数(隐式对象参数) ) 表示调用它们的对象,并出现在第一个实际参数之前。

我不明白为什么这里提到静态这个词?隐式对象参数不是指针this(仅存在于非静态函数中)吗?

在此链接中编辑:链接

引用 :

关键字 this 是右值 (C++11 之前) 纯右值 (C++11 起) 表达式,其值是隐式对象参数(调用非静态成员函数的对象)的地址。它可以出现在以下环境中:

c++ member-functions language-lawyer overload-resolution

16
推荐指数
1
解决办法
1064
查看次数