使用C++中的模板检测不同的字符串文本

Detecting different string literals using templates in C++

本文关键字:字符串 文本 检测 C++ 使用      更新时间:2023-10-16

我正在使用模板来检测不同的字符串文字,我来到了以下代码(尝试使用 C++20(:

#include <iostream>
#include <type_traits>
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, const char*>, int> = 0>
void print_str(T) {
std::cout << "char* print_strn";
}
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, const char8_t*>, int> = 0>
void print_str(T) {
std::cout << "char8_t* print_strn";
}
template <typename T, std::enable_if_t<std::is_same_v<std::decay_t<T>, const wchar_t*>, int> = 0>
void print_str(T) {
std::cout << "wchar_t* print_strn";
}
int main() {
auto a = "hello"; // prints "char* print_str"
print_str(a);
auto b = L"hello"; // prints "wchar_t* print_str"
print_str(b);
auto c = u8"hello"; // prints "char8_t* print_str"
print_str(c);
}

我使用的事实是在 C++20 中,u8前缀声明char8_t类型。但这是我的问题:

  1. 即使前缀从 C++11 开始u8它也使用仅从 C++20 开始的char8_t。那么如何检测前缀u8在 C++11 到 C++20 之间的 UTF-8 字符串呢?
  2. 如何更改模板以检测例如const char*char*哪个相同的功能?我尝试使用remove_const<>但它不起作用,因为它不会从const char*中删除const
  1. 您无法在 C++17 等没有它的语言中检测到char8_t。因此,您必须具有 constexpr 函数,该函数通过检查字符串的内容来检测它是否为 UTF-8。这样的功能对char8_t也有意义。使用char8_t构造非法 UTF-8 字符串很简单。C++17或更少不包含此类功能。

  2. 使用或?std::is_same_v<std::decay_t<T>, const char*> || std::is_same_v<std::decay_t<T>, char*>

  1. 那么我如何检测在 C++11 到 C++20 之间以 u8 为前缀的 UTF-8 字符串呢?

字符串类型无法确保编码。

const char*可用于 utf-8,但也可用于拉丁语-1
以同样的方式const wchar*不需要 utf-16。

有一些启发式的方法来检测编码。

  1. 如何更改我的模板以检测例如常量字符*和字符*哪个相同的功能?我尝试使用remove_const<>但它不起作用,因为它不会从const char*中删除const

const char *!=char* const.

您可以从后者中删除const以获取char*

你可能会这样做

std::is_same_v<std::remove_const_t<std::remove_pointer_t<T>>, char> && std::is_pointer_v<T>

但只需更改为:

void print_str(const char*) { std::cout << "char* print_strn"; }
void print_str(const char8_t*) { std::cout << "char8_t* print_strn"; }
void print_str(const wchar_t*) { std::cout << "wchar_t* print_strn"; }

如果您坚持使用模板:

template <typename T>
void print_str(const T*) {
if constexpr (std::is_same_v<char, T>) {
std::cout << "char* print_strn";
} else if constexpr (std::is_same_v<char8_t, T>) {
std::cout << "char8_t* print_strn";
} else if constexpr (std::is_same_v<wchar_t, T>) {
std::cout << "wchar_t* print_strn";
}
}