将两个char*带入另一个std :: string的字符串构造函数在c ++ 14中工作但不是c ++ 17

Rya*_*ing 17 c++ c++14 c++17

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

#include <string>

int main() {
  std::string src = "hello world";
  const char* end = &src[5];
  std::string dest(src.data(), end);
}
Run Code Online (Sandbox Code Playgroud)

在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 ...]
Run Code Online (Sandbox Code Playgroud)

改变了什么让这次失败?

Rya*_*ing 33

构造dest是试图使用以下构造函数(来自cppreference):

template< class InputIt >
basic_string( InputIt first, InputIt last, 
              const Allocator& alloc = Allocator() );
Run Code Online (Sandbox Code Playgroud)

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

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

std::string dest(src.c_str(), end);
Run Code Online (Sandbox Code Playgroud)

另一个解决方案是呼吁data()str通过const引用:

const auto& const_src = src;
std::string dest(const_src.data(), end);
Run Code Online (Sandbox Code Playgroud)

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

std::string dest(std::as_const(src).data(), end);
Run Code Online (Sandbox Code Playgroud)

  • 另一种可能性是完全摆脱`end`指针:`const char*start = src.c_str(); std :: string dest(start,start + 5);`或者:`char*start = src.data(); std :: string dest(start,start + 5);`或者,只需使用不同的构造函数,例如:`std :: string dest(src.c_str(),5);` (5认同)
  • 您可以使用C++ 17的[`std :: as_const`](http://en.cppreference.com/w/cpp/utility/as_const)来调用`data()`的const版本. (3认同)
  • @Slava当然,和`std :: string :: data()+ 5`和`std :: string :: data()`一样. (3认同)
  • @Slava一个指针是*always*一个迭代器,它不会根据具体情况而改变.在OP问题中,唯一的问题是begin和end迭代器的*type*是不同的(const与非const). (2认同)