字符串构造函数将两个字符* 放入另一个 std::string 在 C++14 中有效,但不适用于 C++17

string constructor taking two char* into another std::string works in c++14 but not c++17

本文关键字:C++14 string 有效 C++17 适用于 不适用 std 另一个 构造函数 两个 字符      更新时间:2023-10-16

以下程序尝试使用第一个字符串和指向第一个字符串中间的指针构造第二个字符串:

#include <string>
int main() {
  std::string src = "hello world";
  const char* end = &src[5];
  std::string dest(src.data(), end);
}

在 C++14 及更早版本中,这有效。但在 C++17 中,调用失败:

error: no matching function for call to ‘std::__cxx11::basic_string<char>::basic_string(char*, const char*&)’
   std::string dest(src.data(), end);
[... full output omitted ...]

是什么改变了导致这失败?

dest的构造试图使用以下构造函数(来自 cpp首选项(:

template< class InputIt >
basic_string( InputIt first, InputIt last, 
              const Allocator& alloc = Allocator() );

这要求firstlast具有完全相同的类型。问题是在 C++17 中,当在非常量std::string上调用时,std::string::data会返回一个非常量指针。这意味着first的类型char*last的类型const char*。由于它们不同,因此无法推断模板参数InputIt,并且调用失败。

无法将模板参数显式指定为构造函数调用,但有一个解决方案。 std::string::c_str仍然返回一个const char*dest的构造可以使用它:

std::string dest(src.c_str(), end);

另一种解决方案是通过 const 引用在str上调用data()

const auto& const_src = src;
std::string dest(const_src.data(), end);

或者,如果您不关心C++14兼容性,则可以使用std::as_const(感谢Mário Feroldi(

std::string dest(std::as_const(src).data(), end);