constexpr string
时间: 2024-05-26 11:07:43 浏览: 19
`constexpr string`指的是在编译时期就可以确定的字符串,可以在编译期间进行计算。其实现方式为使用模板元编程技术和C++11中的`constexpr`特性。
以下是一个`constexpr string`的例子:
```cpp
#include <iostream>
#include <array>
template <typename CharT, CharT... chars>
struct ConstexprString {
static constexpr std::array<CharT, sizeof...(chars) + 1> value{{chars..., '\0'}};
};
int main() {
constexpr auto str = ConstexprString<char, 'H', 'e', 'l', 'l', 'o'>::value;
std::cout << str.data() << std::endl;
return 0;
}
```
在上述例子中,我们定义了一个模板类`ConstexprString`,它接受两个参数:字符类型`CharT`和一系列字符`chars...`。我们使用了可变参数模板和折叠表达式将这些字符打包为一个`std::array`类型的静态成员变量`value`。在`main`函数中,我们通过调用该静态成员变量来获得一个`constexpr string`类型的字符串。
需要注意的是,在编译期间计算字符串可能会增加编译时间和代码长度,因此应谨慎使用。
相关问题
error: call to non-'constexpr' function 'std::size_t std::hash<std::__cxx11::basic_string<char> >::operator()(const string&) const'
这个错误是因为编译器无法确定 `std::hash<std::string>::operator()` 函数的返回值是否是编译期常量,因此不能在 `constexpr` 上下文中使用该函数。
解决方法是使用 `constexpr` 关键字显式地声明 `std::hash<std::string>::operator()` 函数是一个 `constexpr` 函数。示例代码如下:
```c++
#include <iostream>
#include <functional>
#include <string>
using namespace std;
// 显式声明 std::hash<std::string>::operator() 是一个 constexpr 函数
namespace std {
template<>
struct hash<string> {
constexpr size_t operator()(const string& str) const {
return std::_Hash_impl::hash(str.data(), str.length());
}
};
}
int main() {
unordered_map<size_t, string> map = {
{hash<string>()("hello"), "Hello World!"},
{hash<string>()("world"), "World Hello!"},
{hash<string>()("good"), "Good Morning!"},
{hash<string>()("night"), "Good Night!"}
};
string str;
cout << "Please enter a string: ";
getline(cin, str);
switch (hash<string>()(str)) {
case hash<string>()("hello"):
cout << map[hash<string>()("hello")] << endl;
break;
case hash<string>()("world"):
cout << map[hash<string>()("world")] << endl;
break;
case hash<string>()("good"):
cout << map[hash<string>()("good")] << endl;
break;
case hash<string>()("night"):
cout << map[hash<string>()("night")] << endl;
break;
default:
cout << "Unknown input!" << endl;
break;
}
return 0;
}
```
在上面的代码中,我们显式声明了 `std::hash<std::string>::operator()` 函数是一个 `constexpr` 函数,编译器就可以确定该函数的返回值是编译期常量,从而避免了上述编译错误。
cpp17的std::string_view
std::string_view是C++17中的新类型,它是一个用来表示字符串的轻量级视图,不拥有字符串的所有权,而是指向一个已有的字符串对象。它类似于指向字符串的指针,但是提供了更多的安全性和便利性。
std::string_view的定义如下:
```
namespace std {
template<class charT, class traits = std::char_traits<charT>>
class basic_string_view {
public:
using value_type = charT;
using traits_type = traits;
using pointer = value_type*;
using const_pointer = const value_type*;
using reference = value_type&;
using const_reference = const value_type&;
using const_iterator = const_pointer;
using iterator = const_iterator;
using size_type = std::size_t;
using difference_type = std::ptrdiff_t;
// 构造函数
constexpr basic_string_view() noexcept;
constexpr basic_string_view(const basic_string_view&) noexcept = default;
constexpr basic_string_view(const charT* str);
constexpr basic_string_view(const charT* str, size_type len);
// 迭代器
constexpr const_iterator begin() const noexcept;
constexpr const_iterator end() const noexcept;
constexpr const_iterator cbegin() const noexcept;
constexpr const_iterator cend() const noexcept;
// 容量
constexpr size_type size() const noexcept;
constexpr size_type length() const noexcept;
constexpr size_type max_size() const noexcept;
constexpr bool empty() const noexcept;
// 元素访问
constexpr const_reference operator[](size_type pos) const noexcept;
constexpr const_reference at(size_type pos) const;
constexpr const_reference front() const noexcept;
constexpr const_reference back() const noexcept;
constexpr const_pointer data() const noexcept;
// 子串
constexpr basic_string_view substr(size_type pos, size_type n = npos) const;
// 查找
constexpr size_type find(basic_string_view v, size_type pos = 0) const noexcept;
constexpr size_type find(charT c, size_type pos = 0) const noexcept;
constexpr size_type rfind(basic_string_view v, size_type pos = npos) const noexcept;
constexpr size_type rfind(charT c, size_type pos = npos) const noexcept;
constexpr size_type find_first_of(basic_string_view v, size_type pos = 0) const noexcept;
constexpr size_type find_first_of(charT c, size_type pos = 0) const noexcept;
constexpr size_type find_last_of(basic_string_view v, size_type pos = npos) const noexcept;
constexpr size_type find_last_of(charT c, size_type pos = npos) const noexcept;
// 操作符
friend bool operator==(basic_string_view lhs, basic_string_view rhs) noexcept;
friend bool operator!=(basic_string_view lhs, basic_string_view rhs) noexcept;
friend bool operator<(basic_string_view lhs, basic_string_view rhs) noexcept;
friend bool operator<=(basic_string_view lhs, basic_string_view rhs) noexcept;
friend bool operator>(basic_string_view lhs, basic_string_view rhs) noexcept;
friend bool operator>=(basic_string_view lhs, basic_string_view rhs) noexcept;
// 常量
static constexpr size_type npos = size_type(-1);
};
// 类型别名
using string_view = basic_string_view<char>;
using wstring_view = basic_string_view<wchar_t>;
using u16string_view = basic_string_view<char16_t>;
using u32string_view = basic_string_view<char32_t>;
}
```
std::string_view的使用非常简单,可以通过构造函数传入一个已有的字符串对象,也可以传入一个C风格字符串(以'\0'结尾)。然后就可以像操作字符串一样使用std::string_view了,例如获取字符串的长度、访问字符串中的字符、查找字符串等等。和std::string不同的是,std::string_view没有修改字符串的操作。
std::string_view的好处在于它比std::string更轻量级,不需要额外的内存分配和复制操作,因此在一些需要高效处理字符串的场景下,使用std::string_view可以减少不必要的开销。例如,在函数参数中传递字符串时,可以使用std::string_view来避免不必要的内存分配和复制,提高程序的性能。