VS2019中使用char8_t编程后,代码兼容2017的方法

介绍:
由于VS2019中启用了char8_t,decltype(u8"字符串") 是 const char8_t(&)[ N ],导致许多代码需要变更。
然而一旦变更后,回到VS2017中反而会因为重载和模板匹配的问题导致错误,这就需要一些兼容机制来处理移植问题。

一个是https://github.com/tahonermann/char8_t-remediation。用法不太清楚。
下面介绍一下我编写的UTF8Compatible.h
可用于VS2017~VS2019之间,其他编译器暂未实验相信改的不多。至于不支持u8""的低版本编译器本就不考虑在内了。

#pragma once
#ifndef _H_UTF8_H_
#define _H_UTF8_H_

#include <string>
#include <type_traits>
using namespace std::literals;

#if !defined(__cpp_char8_t)

using char8_t = unsigned char;
namespace std
{
    using u8string = std::basic_string<char8_t, char_traits<char8_t>, allocator<char8_t>>;
    using u8string_view = std::basic_string_view<char8_t>;
}
template<typename T> struct StringLiteralHelp;
template<int N>     struct StringLiteralHelp<const char(&)[N]>
{
    using type = const char8_t(&)[N];
};
template<>     struct StringLiteralHelp<char>
{
    using type = char8_t;
};

//用于传参与赋值指针
#define U8(x) ((StringLiteralHelp<decltype(u8##x)>::type)(u8##x))
//原始的字符串形式,用于构造数组
#define U8c(x) (u8##x) 

_NODISCARD inline std::u8string operator "" ___u8s(const char* _Str, size_t _Len)
{
    return (std::u8string((const char8_t*)_Str, _Len));
}

#define U8S(x) (u8##x##___u8s)

#else


#define U8(x) (u8##x)   //用于传参与赋值指针,或赋值给auto 、auto&、auto*、const char8_t*、赋值。同样可用于字符 U8('中')
#define U8c(x) (u8##x)  //原始的字符串形式,唯一用途是用于给数组初始化 char8_t s[N] = U8c("xxxx")、char8_t s[] = U8c("xxxx")
#define U8S(x) (u8##x##s) //构造一个u8string

#endif

#endif //_H_UTF8_H_

附带u8string和 u8string_view的可视化 UTF8Compatible.natvis

<?xml version="1.0" encoding="utf-8"?> 
<AutoVisualizer xmlns="http://schemas.microsoft.com/vstudio/debugger/natvis/2010">
  <Type Name="std::basic_string&lt;unsigned char,*&gt;">
    <Intrinsic Name="size" Expression="_Mypair._Myval2._Mysize" />
    <Intrinsic Name="capacity" Expression="_Mypair._Myval2._Myres" />
    <!-- _BUF_SIZE = 16 / sizeof(char) &lt; 1 ? 1 : 16 / sizeof(char) == 16 -->
    <Intrinsic Name="bufSize" Expression="16" />
    <Intrinsic Name="isShortString" Expression="capacity() &lt; bufSize()" />
    <Intrinsic Name="isLongString" Expression="capacity() &gt;= bufSize()" />
    <DisplayString Condition="isShortString()">{_Mypair._Myval2._Bx._Buf,s8}</DisplayString>
    <DisplayString Condition="isLongString()">{_Mypair._Myval2._Bx._Ptr,s8}</DisplayString>
    <StringView Condition="isShortString()">_Mypair._Myval2._Bx._Buf,s8</StringView>
    <StringView Condition="isLongString()">_Mypair._Myval2._Bx._Ptr,s8</StringView>
    <Expand>
      <Item Name="[size]" ExcludeView="simple">size()</Item>
      <Item Name="[capacity]" ExcludeView="simple">capacity()</Item>
      <Item Name="[allocator]" ExcludeView="simple">_Mypair</Item>
      <ArrayItems>
        <Size>_Mypair._Myval2._Mysize</Size>
        <ValuePointer Condition="isShortString()">_Mypair._Myval2._Bx._Buf</ValuePointer>
        <ValuePointer Condition="isLongString()">_Mypair._Myval2._Bx._Ptr</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>
  <Type Name="std::basic_string&lt;signed char,*&gt;">
    <Intrinsic Name="size" Expression="_Mypair._Myval2._Mysize" />
    <Intrinsic Name="capacity" Expression="_Mypair._Myval2._Myres" />
    <!-- _BUF_SIZE = 16 / sizeof(char) &lt; 1 ? 1 : 16 / sizeof(char) == 16 -->
    <Intrinsic Name="bufSize" Expression="16" />
    <Intrinsic Name="isShortString" Expression="capacity() &lt; bufSize()" />
    <Intrinsic Name="isLongString" Expression="capacity() &gt;= bufSize()" />
    <DisplayString Condition="isShortString()">{_Mypair._Myval2._Bx._Buf,s8}</DisplayString>
    <DisplayString Condition="isLongString()">{_Mypair._Myval2._Bx._Ptr,s8}</DisplayString>
    <StringView Condition="isShortString()">_Mypair._Myval2._Bx._Buf,s8</StringView>
    <StringView Condition="isLongString()">_Mypair._Myval2._Bx._Ptr,s8</StringView>
    <Expand>
      <Item Name="[size]" ExcludeView="simple">size()</Item>
      <Item Name="[capacity]" ExcludeView="simple">capacity()</Item>
      <Item Name="[allocator]" ExcludeView="simple">_Mypair</Item>
      <ArrayItems>
        <Size>_Mypair._Myval2._Mysize</Size>
        <ValuePointer Condition="isShortString()">_Mypair._Myval2._Bx._Buf</ValuePointer>
        <ValuePointer Condition="isLongString()">_Mypair._Myval2._Bx._Ptr</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>
  <Type Name="std::basic_string_view&lt;unsigned char,*&gt;">
    <Intrinsic Name="size" Expression="_Mysize" />
    <Intrinsic Name="data" Expression="_Mydata" />
    <DisplayString>{_Mydata,[_Mysize]s8}</DisplayString>
    <Expand>
      <Item Name="[size]" ExcludeView="simple">size()</Item>
      <ArrayItems>
        <Size>size()</Size>
        <ValuePointer>data()</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>
  <Type Name="std::basic_string_view&lt;signed char,*&gt;">
    <Intrinsic Name="size" Expression="_Mysize" />
    <Intrinsic Name="data" Expression="_Mydata" />
    <DisplayString>{_Mydata,[_Mysize]s8}</DisplayString>
    <Expand>
      <Item Name="[size]" ExcludeView="simple">size()</Item>
      <ArrayItems>
        <Size>size()</Size>
        <ValuePointer>data()</ValuePointer>
      </ArrayItems>
    </Expand>
  </Type>
</AutoVisualizer>
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值