以下程序尝试使用第一个字符串和指向第一个字符串中间的指针构造第二个字符串:
#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
的构造尝试使用以下构造函数(来自cppreference):
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
这要求
first
和 last
具有完全相同的类型。问题是,在 C++17 中,当调用非常量 std::string::data
时,会返回一个 非常量指针。这意味着 std::string
的类型是 first
,而 char*
的类型是 last
。由于它们不同,因此无法推导模板参数const char*
,并且调用失败。无法显式指定构造函数调用的模板参数,但有一个解决方案。
InputIt
仍然返回一个
std::string::c_str
并且
const char*
的构造可以使用它:dest
另一种解决方案是通过 const 引用在
std::string dest(src.c_str(), end);
上调用
data()
:str
或者,如果您不关心 C++14 兼容性,您可以使用
const auto& const_src = src;
std::string dest(const_src.data(), end);
(感谢 Mário Feroldi)
std::as_const