相关疑难解决方法(0)

为什么指针衰减优先于推导出的模板?

假设我正在编写一个函数来打印字符串的长度:

template <size_t N>
void foo(const char (&s)[N]) {
    std::cout << "array, size=" << N-1 << std::endl;
}

foo("hello") // prints array, size=5
Run Code Online (Sandbox Code Playgroud)

现在我想扩展foo以支持数组:

void foo(const char* s) {
    std::cout << "raw, size=" << strlen(s) << std::endl;
}
Run Code Online (Sandbox Code Playgroud)

但事实证明,这破坏了我原来的预期用途:

foo("hello") // now prints raw, size=5
Run Code Online (Sandbox Code Playgroud)

为什么?这不需要数组到指针的转换,而模板是完全匹配的吗?有没有办法确保我的数组函数被调用?

c++ arrays overload-resolution

51
推荐指数
1
解决办法
1446
查看次数

左值参考和右值参考之间的重载分辨率

#include <iostream>

using namespace std;

void func(int (&ref)[6]) { cout << "#1" << endl; }
void func(int * &&ref) { cout << "#2" << endl; }

int main()
{
  int arr[6];
  func(arr); // g++(5.4): ambiguous, clang++(3.8): #2, vc++(19.11): #1

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

这两个函数都是完全匹配.以下是标准的引用:

标准转换序列S1是比标准转换序列S2更好的转换序列

...

S1和S2是引用绑定(8.5.3),并且都不引用没有ref-qualifier声明的非静态成员函数的隐式对象参数,S1将rvalue引用绑定到rvalue,S2绑定左值引用.

这不是意味着第二个更好吗?

更新:

一个相关的问题.以下代码是它的简化版本.

#include <iostream>

using namespace std;

void func(int *&) { cout << "#1" << endl; }
void func(int *&&) { cout << "#2" << endl; }

int main()
{
  int arr[6]; …
Run Code Online (Sandbox Code Playgroud)

c++ overloading rvalue-reference language-lawyer

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

C++ 0x右值引用和临时值

(我在comp.std.c ++上询问了这个问题的变体,但没有得到答案.)

为什么f(arg)在这段代码中的调用调用const ref重载f

void f(const std::string &); //less efficient
void f(std::string &&); //more efficient

void g(const char * arg)
{
     f(arg);
}
Run Code Online (Sandbox Code Playgroud)

我的直觉说f(string &&)应该选择重载,因为arg无论如何都需要转换为临时值,并且临时匹配rvalue引用比lvalue引用更好.

这不是GCC和 MSVC中发生的事情(编辑:谢谢Sumant:它不会发生在GCC 4.3-4.5中).至少在G ++和 MSVC中,任何左值都不会绑定到右值引用参数,即使创建了一个中间临时值.实际上,如果不存在const ref重载,编译器会诊断出错误.然而,编写f(arg + 0)f(std::string(arg)) 选择右值引用过载如你所愿.

从我对C++ 0x标准的阅读中,似乎在考虑是否f(string &&)可行时应考虑将const char*隐式转换为字符串,就像传递const lvalue ref参数时一样.第13.3节(重载解析)在很多地方没有区分rvalue refs和const引用.此外,似乎阻止左值绑定到右值引用(13.3.3.1.4/3)的规则不适用,如果存在中间临时值 - 毕竟,从临时值移动是完全安全的.

这是:

  1. 我误读/误解了标准,其中实现的行为是预期的行为,并且有一个很好的理由为什么我的例子应该按照它的方式行事?
  2. 编译器供应商以某种方式犯下的错误?或者是基于共同实施策略的错误?或者是其他供应商复制的GCC(首次实施此左值/右值参考绑定规则)中的错误?
  3. 标准中的缺陷,或意外后果,或应澄清的内容?

编辑:我有一个相关的后续问题:C++ 0x rvalue引用 - lvalues-rvalue绑定

c++ temporary rvalue-reference c++11

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

C++ 11 - 区分右值指针

如何将变量区分为编译器构造的字符串?

例如,虽然右值"Hello, World"是类型const char*.const char*本身并不意味着指针不能改变.一个char* const指针不能改变,但是这不是什么编译器构成.

这是否意味着,对于任何拥有a的容器,const char*数据应该通过C++的移动语义之外的方式复制?有没有办法只移动编译器构造的字符串并保留所有其他字符串?

例如,在GCC 4.5.2,它返回类型的方法int,而不是int&被当作返回int&&.我不知道实际的标准是否应该是这样的,但这就是海湾合作委员会暂时做的事情.

编辑:澄清一下,我的意思是应该复制指针指向的实际内存.这意味着必须分配新内存,并且应将指针中的数据复制到新位置.

c++ string rvalue-reference move-semantics c++11

2
推荐指数
1
解决办法
1930
查看次数