0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Allman 好きのための .clang-format

Last updated at Posted at 2023-04-08

clang-format で Allman にしたい場合の .clang-format を提示します。
Googleスタイルをベースに3か所変更してます。
添付した「.clang-format(Allman適用済み)」をホームディレクトリにおいてください。
Allman ではどういう風に整形されるのか分からない方は、文末に整形例を添付しましたのでそちらをご覧ください。

※ IndentWidth を 4 にしてありますが、これを 2 に変える場合は、AccessModifierOffset も -4 から -2 に変えてください。

.clang-format のカスタマイズについては:

もご覧ください。

AccessModifierOffset とは:
IndentWidth が 4だと・・・

class Calc
{
    public: // ← これもインデントされてしまう。
    static int add(int a, int b);
};

これを AccessModifierOffset で補正します。IndentWidth をマイナスにした数値にしておけば・・・

class Calc
{
public: // ← インデント(+4 -4 = 0) でインデントされない。
    static int add(int a, int b);
};

となり、わりと一般的な整形結果となります。

Googleスタイルからの差分を調べる
clang-format --style=Google --dump-config > .clang-format.original
diff .clang-format.original .clang-format
上記実行結果(Googleスタイルからの差分)
-AccessModifierOffset: -1
+AccessModifierOffset: -4
-BreakBeforeBraces: Attach
+BreakBeforeBraces: Allman
-IndentWidth:     2
+IndentWidth:     4
.clang-format(Allman適用済み)
---
Language:        Cpp
# BasedOnStyle:  Google
AccessModifierOffset: -4
AlignAfterOpenBracket: Align
AlignArrayOfStructures: None
AlignConsecutiveAssignments:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    true
AlignConsecutiveBitFields:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignConsecutiveDeclarations:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignConsecutiveMacros:
  Enabled:         false
  AcrossEmptyLines: false
  AcrossComments:  false
  AlignCompound:   false
  PadOperators:    false
AlignEscapedNewlines: Left
AlignOperands:   Align
AlignTrailingComments: true
AllowAllArgumentsOnNextLine: true
AllowAllParametersOfDeclarationOnNextLine: true
AllowShortEnumsOnASingleLine: true
AllowShortBlocksOnASingleLine: Never
AllowShortCaseLabelsOnASingleLine: false
AllowShortFunctionsOnASingleLine: All
AllowShortLambdasOnASingleLine: All
AllowShortIfStatementsOnASingleLine: WithoutElse
AllowShortLoopsOnASingleLine: true
AlwaysBreakAfterDefinitionReturnType: None
AlwaysBreakAfterReturnType: None
AlwaysBreakBeforeMultilineStrings: true
AlwaysBreakTemplateDeclarations: Yes
AttributeMacros:
  - __capability
BinPackArguments: true
BinPackParameters: true
BraceWrapping:
  AfterCaseLabel:  false
  AfterClass:      false
  AfterControlStatement: Never
  AfterEnum:       false
  AfterFunction:   false
  AfterNamespace:  false
  AfterObjCDeclaration: false
  AfterStruct:     false
  AfterUnion:      false
  AfterExternBlock: false
  BeforeCatch:     false
  BeforeElse:      false
  BeforeLambdaBody: false
  BeforeWhile:     false
  IndentBraces:    false
  SplitEmptyFunction: true
  SplitEmptyRecord: true
  SplitEmptyNamespace: true
BreakBeforeBinaryOperators: None
BreakBeforeConceptDeclarations: Always
BreakBeforeBraces: Allman
BreakBeforeInheritanceComma: false
BreakInheritanceList: BeforeColon
BreakBeforeTernaryOperators: true
BreakConstructorInitializersBeforeComma: false
BreakConstructorInitializers: BeforeColon
BreakAfterJavaFieldAnnotations: false
BreakStringLiterals: true
ColumnLimit:     80
CommentPragmas:  '^ IWYU pragma:'
QualifierAlignment: Leave
CompactNamespaces: false
ConstructorInitializerIndentWidth: 4
ContinuationIndentWidth: 4
Cpp11BracedListStyle: true
DeriveLineEnding: true
DerivePointerAlignment: true
DisableFormat:   false
EmptyLineAfterAccessModifier: Never
EmptyLineBeforeAccessModifier: LogicalBlock
ExperimentalAutoDetectBinPacking: false
PackConstructorInitializers: NextLine
BasedOnStyle:    ''
ConstructorInitializerAllOnOneLineOrOnePerLine: false
AllowAllConstructorInitializersOnNextLine: true
FixNamespaceComments: true
ForEachMacros:
  - foreach
  - Q_FOREACH
  - BOOST_FOREACH
IfMacros:
  - KJ_IF_MAYBE
IncludeBlocks:   Regroup
IncludeCategories:
  - Regex:           '^<ext/.*\.h>'
    Priority:        2
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '^<.*\.h>'
    Priority:        1
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '^<.*'
    Priority:        2
    SortPriority:    0
    CaseSensitive:   false
  - Regex:           '.*'
    Priority:        3
    SortPriority:    0
    CaseSensitive:   false
IncludeIsMainRegex: '([-_](test|unittest))?$'
IncludeIsMainSourceRegex: ''
IndentAccessModifiers: false
IndentCaseLabels: true
IndentCaseBlocks: false
IndentGotoLabels: true
IndentPPDirectives: None
IndentExternBlock: AfterExternBlock
IndentRequiresClause: true
IndentWidth:     4
IndentWrappedFunctionNames: false
InsertBraces:    false
InsertTrailingCommas: None
JavaScriptQuotes: Leave
JavaScriptWrapImports: true
KeepEmptyLinesAtTheStartOfBlocks: false
LambdaBodyIndentation: Signature
MacroBlockBegin: ''
MacroBlockEnd:   ''
MaxEmptyLinesToKeep: 1
NamespaceIndentation: None
ObjCBinPackProtocolList: Never
ObjCBlockIndentWidth: 2
ObjCBreakBeforeNestedBlockParam: true
ObjCSpaceAfterProperty: false
ObjCSpaceBeforeProtocolList: true
PenaltyBreakAssignment: 2
PenaltyBreakBeforeFirstCallParameter: 1
PenaltyBreakComment: 300
PenaltyBreakFirstLessLess: 120
PenaltyBreakOpenParenthesis: 0
PenaltyBreakString: 1000
PenaltyBreakTemplateDeclaration: 10
PenaltyExcessCharacter: 1000000
PenaltyReturnTypeOnItsOwnLine: 200
PenaltyIndentedWhitespace: 0
PointerAlignment: Left
PPIndentWidth:   -1
RawStringFormats:
  - Language:        Cpp
    Delimiters:
      - cc
      - CC
      - cpp
      - Cpp
      - CPP
      - 'c++'
      - 'C++'
    CanonicalDelimiter: ''
    BasedOnStyle:    google
  - Language:        TextProto
    Delimiters:
      - pb
      - PB
      - proto
      - PROTO
    EnclosingFunctions:
      - EqualsProto
      - EquivToProto
      - PARSE_PARTIAL_TEXT_PROTO
      - PARSE_TEST_PROTO
      - PARSE_TEXT_PROTO
      - ParseTextOrDie
      - ParseTextProtoOrDie
      - ParseTestProto
      - ParsePartialTestProto
    CanonicalDelimiter: pb
    BasedOnStyle:    google
ReferenceAlignment: Pointer
ReflowComments:  true
RemoveBracesLLVM: false
RequiresClausePosition: OwnLine
SeparateDefinitionBlocks: Leave
ShortNamespaceLines: 1
SortIncludes:    CaseSensitive
SortJavaStaticImport: Before
SortUsingDeclarations: true
SpaceAfterCStyleCast: false
SpaceAfterLogicalNot: false
SpaceAfterTemplateKeyword: true
SpaceBeforeAssignmentOperators: true
SpaceBeforeCaseColon: false
SpaceBeforeCpp11BracedList: false
SpaceBeforeCtorInitializerColon: true
SpaceBeforeInheritanceColon: true
SpaceBeforeParens: ControlStatements
SpaceBeforeParensOptions:
  AfterControlStatements: true
  AfterForeachMacros: true
  AfterFunctionDefinitionName: false
  AfterFunctionDeclarationName: false
  AfterIfMacros:   true
  AfterOverloadedOperator: false
  AfterRequiresInClause: false
  AfterRequiresInExpression: false
  BeforeNonEmptyParentheses: false
SpaceAroundPointerQualifiers: Default
SpaceBeforeRangeBasedForLoopColon: true
SpaceInEmptyBlock: false
SpaceInEmptyParentheses: false
SpacesBeforeTrailingComments: 2
SpacesInAngles:  Never
SpacesInConditionalStatement: false
SpacesInContainerLiterals: true
SpacesInCStyleCastParentheses: false
SpacesInLineCommentPrefix:
  Minimum:         1
  Maximum:         -1
SpacesInParentheses: false
SpacesInSquareBrackets: false
SpaceBeforeSquareBrackets: false
BitFieldColonSpacing: Both
Standard:        Auto
StatementAttributeLikeMacros:
  - Q_EMIT
StatementMacros:
  - Q_UNUSED
  - QT_REQUIRE_VERSION
TabWidth:        8
UseCRLF:         false
UseTab:          Never
WhitespaceSensitiveMacros:
  - STRINGIZE
  - PP_STRINGIZE
  - BOOST_PP_STRINGIZE
  - NS_SWIFT_NAME
  - CF_SWIFT_NAME
...


Allmanで整形したソース
/* strconv-again.h v1.0.0          */
/* Last Modified: 2023/04/08 02:53 */
#ifndef STRCONV_AGAIN_H
#define STRCONV_AGAIN_H

#include <stdarg.h>
#include <windows.h>

#include <codecvt>
#include <iostream>
#include <locale>
#include <sstream>
#include <string>
#include <vector>

static inline std::wstring cp_to_wide(const std::string &s, UINT codepage)
{
    int in_length = (int)s.length();
    int out_length =
        MultiByteToWideChar(codepage, 0, s.c_str(), in_length, 0, 0);
    std::wstring result(out_length, L'\0');
    if (out_length)
        MultiByteToWideChar(codepage, 0, s.c_str(), in_length, &result[0],
                            out_length);
    return result;
}
static inline std::string wide_to_cp(const std::wstring &s, UINT codepage)
{
    int in_length = (int)s.length();
    int out_length =
        WideCharToMultiByte(codepage, 0, s.c_str(), in_length, 0, 0, 0, 0);
    std::string result(out_length, '\0');
    if (out_length)
        WideCharToMultiByte(codepage, 0, s.c_str(), in_length, &result[0],
                            out_length, 0, 0);
    return result;
}

static inline std::string cp_to_utf8(const std::string &s, UINT codepage)
{
    if (codepage == CP_UTF8) return s;
    std::wstring wide = cp_to_wide(s, codepage);
    return wide_to_cp(wide, CP_UTF8);
}
static inline std::string utf8_to_cp(const std::string &s, UINT codepage)
{
    if (codepage == CP_UTF8) return s;
    std::wstring wide = cp_to_wide(s, CP_UTF8);
    return wide_to_cp(wide, codepage);
}

static inline std::wstring ansi_to_wide(const std::string &s)
{
    return cp_to_wide(s, CP_ACP);
}
static inline std::string wide_to_ansi(const std::wstring &s)
{
    return wide_to_cp(s, CP_ACP);
}

static inline std::wstring sjis_to_wide(const std::string &s)
{
    return cp_to_wide(s, 932);
}
static inline std::string wide_to_sjis(const std::wstring &s)
{
    return wide_to_cp(s, 932);
}

static inline std::wstring utf8_to_wide(const std::string &s)
{
    return cp_to_wide(s, CP_UTF8);
}
static inline std::string wide_to_utf8(const std::wstring &s)
{
    return wide_to_cp(s, CP_UTF8);
}

static inline std::string ansi_to_utf8(const std::string &s)
{
    return cp_to_utf8(s, CP_ACP);
}
static inline std::string utf8_to_ansi(const std::string &s)
{
    return utf8_to_cp(s, CP_ACP);
}

static inline std::string sjis_to_utf8(const std::string &s)
{
    return cp_to_utf8(s, 932);
}
static inline std::string utf8_to_sjis(const std::string &s)
{
    return utf8_to_cp(s, 932);
}

#ifdef __cpp_char8_t
static inline std::u8string utf8_to_char8(const std::string &s)
{
    return std::u8string(s.begin(), s.end());
}
static inline std::string char8_to_utf8(const std::u8string &s)
{
    return std::string(s.begin(), s.end());
}

static inline std::wstring char8_to_wide(const std::u8string &s)
{
    return cp_to_wide(char8_to_utf8(s), CP_UTF8);
}
static inline std::u8string wide_to_char8(const std::wstring &s)
{
    return utf8_to_char8(wide_to_cp(s, CP_UTF8));
}

static inline std::u8string cp_to_char8(const std::string &s, UINT codepage)
{
    return utf8_to_char8(cp_to_utf8(s, codepage));
}
static inline std::string char8_to_cp(const std::u8string &s, UINT codepage)
{
    return utf8_to_cp(char8_to_utf8(s), codepage);
}

static inline std::u8string ansi_to_char8(const std::string &s)
{
    return cp_to_char8(s, CP_ACP);
}
static inline std::string char8_to_ansi(const std::u8string &s)
{
    return char8_to_cp(s, CP_ACP);
}

static inline std::u8string sjis_to_char8(const std::string &s)
{
    return cp_to_char8(s, 932);
}
static inline std::string char8_to_sjis(const std::u8string &s)
{
    return char8_to_cp(s, 932);
}
#endif

#if defined(_MSC_VER)
#pragma warning(push)
#pragma warning(disable : 4996)
#endif

static inline std::string char16_to_utf8(const std::u16string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> convert;
        return convert.to_bytes(s);
    }
    catch (...)
    {
        return "";
    }
}

static inline std::u16string utf8_to_char16(const std::string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> convert;
        return convert.from_bytes(s);
    }
    catch (...)
    {
        return u"";
    }
}

static inline std::string char16_to_cp(const std::u16string &s,
                                       unsigned int codepage)
{
    return utf8_to_cp(char16_to_utf8(s), codepage);
}

static inline std::string char32_to_utf8(const std::u32string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
        return convert.to_bytes(s);
    }
    catch (...)
    {
        return "";
    }
}

static inline std::u32string utf8_to_char32(const std::string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
        return convert.from_bytes(s);
    }
    catch (...)
    {
        return U"";
    }
}

static inline std::string char32_to_cp(const std::u32string &s,
                                       unsigned int codepage)
{
    return utf8_to_cp(char32_to_utf8(s), codepage);
}

#ifdef __cpp_char8_t
static inline std::u8string char16_to_char8(const std::u16string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> convert;
        return utf8_to_char8(convert.to_bytes(s));
    }
    catch (...)
    {
        return u8"";
    }
}

static inline std::u16string char8_to_char16(const std::u8string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char16_t>, char16_t> convert;
        return convert.from_bytes(char8_to_utf8(s));
    }
    catch (...)
    {
        return u"";
    }
}

static inline std::u8string char32_to_char8(const std::u32string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
        return utf8_to_char8(convert.to_bytes(s));
    }
    catch (...)
    {
        return u8"";
    }
}

static inline std::u32string char8_to_char32(const std::u8string &s)
{
    try
    {
        std::wstring_convert<std::codecvt_utf8<char32_t>, char32_t> convert;
        return convert.from_bytes(char8_to_utf8(s));
    }
    catch (...)
    {
        return U"";
    }
}
#endif

static inline std::wstring vformat(const wchar_t *format, va_list args)
{
    int len = _vsnwprintf(0, 0, format, args);
    if (len < 0) return L"";
    std::vector<wchar_t> buffer(len + 1);
    len = _vsnwprintf(&buffer[0], len, format, args);
    if (len < 0) return L"";
    buffer[len] = L'\0';
    return &buffer[0];
}
static inline std::string vformat(const char *format, va_list args)
{
    int len = _vsnprintf(0, 0, format, args);
    if (len < 0) return "";
    std::vector<char> buffer(len + 1);
    len = _vsnprintf(&buffer[0], len, format, args);
    if (len < 0) return "";
    buffer[len] = '\0';
    return &buffer[0];
}
#ifdef __cpp_char8_t
static inline std::u8string vformat(const char8_t *format, va_list args)
{
    int len = _vsnprintf(0, 0, (const char *)format, args);
    if (len < 0) return u8"";
    std::vector<char> buffer(len + 1);
    len = _vsnprintf(&buffer[0], len, (const char *)format, args);
    if (len < 0) return u8"";
    buffer[len] = '\0';
    return (char8_t *)&buffer[0];
}
#endif

#if defined(_MSC_VER)
#pragma warning(pop)
#endif

static inline std::wstring format(const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::wstring s = vformat(format, args);
    va_end(args);
    return s;
}
static inline std::string format(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    std::string s = vformat(format, args);
    va_end(args);
    return s;
}
#ifdef __cpp_char8_t
static inline std::u8string format(const char8_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::u8string s = vformat(format, args);
    va_end(args);
    return s;
}
#endif

static inline void format(std::ostream &ostrm, const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::wstring s = vformat(format, args);
    va_end(args);
    ostrm << wide_to_utf8(s) << std::flush;
}
static inline void format(std::ostream &ostrm, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    std::string s = vformat(format, args);
    va_end(args);
    ostrm << s << std::flush;
}
#ifdef __cpp_char8_t
static inline void format(std::ostream &ostrm, const char8_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::u8string s = vformat(format, args);
    va_end(args);
    ostrm << char8_to_utf8(s) << std::flush;
}
#endif

static inline std::string formatA(const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::wstring s = vformat(format, args);
    va_end(args);
    return wide_to_ansi(s);
}
static inline std::string formatA(const char *format, ...)
{
    va_list args;
    va_start(args, format);
    std::string s = vformat(format, args);
    va_end(args);
    return utf8_to_ansi(s);
}
#ifdef __cpp_char8_t
static inline std::string formatA(const char8_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::u8string s = vformat(format, args);
    va_end(args);
    return char8_to_ansi(s);
}
#endif

static inline void formatA(std::ostream &ostrm, const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::wstring s = vformat(format, args);
    va_end(args);
    ostrm << wide_to_ansi(s) << std::flush;
}
static inline void formatA(std::ostream &ostrm, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    std::string s = vformat(format, args);
    va_end(args);
    ostrm << utf8_to_ansi(s) << std::flush;
}
#ifdef __cpp_char8_t
static inline void formatA(std::ostream &ostrm, const char8_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::u8string s = vformat(format, args);
    va_end(args);
    ostrm << char8_to_ansi(s) << std::flush;
}
#endif

static inline void dbgmsg(const wchar_t *title, const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::wstring s = vformat(format, args);
    va_end(args);
    MessageBoxW(0, s.c_str(), title, MB_OK);
}
static inline void dbgmsg(const char *title, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    std::string s = vformat(format, args);
    va_end(args);
    MessageBoxW(0, utf8_to_wide(s).c_str(), utf8_to_wide(title).c_str(), MB_OK);
}
#ifdef __cpp_char8_t
static inline void dbgmsg(const char8_t *title, const char8_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::u8string s = vformat(format, args);
    va_end(args);
    MessageBoxW(0, char8_to_wide(s).c_str(), char8_to_wide(title).c_str(),
                MB_OK);
}
#endif

static inline HANDLE handle_for_ostream(std::ostream &ostrm)
{
    if (&ostrm == &std::cout)
    {
        return GetStdHandle(STD_OUTPUT_HANDLE);
    }
    else if (&ostrm == &std::cerr)
    {
        return GetStdHandle(STD_ERROR_HANDLE);
    }
    return INVALID_HANDLE_VALUE;
}
static inline void dbgout(std::ostream &ostrm, const wchar_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::wstring ws = vformat(format, args);
    va_end(args);
    HANDLE h = handle_for_ostream(ostrm);
    if (h == INVALID_HANDLE_VALUE)
    {
        return;
    }
    DWORD dwNumberOfCharsWrite;
    if (GetFileType(h) != FILE_TYPE_CHAR)
    {
        std::string s = wide_to_cp(ws, GetConsoleOutputCP());
        WriteFile(h, s.c_str(), (DWORD)s.size(), &dwNumberOfCharsWrite, NULL);
    }
    else
    {
        WriteConsoleW(h, ws.c_str(), (DWORD)ws.size(), &dwNumberOfCharsWrite,
                      NULL);
    }
}
static inline void dbgout(std::ostream &ostrm, const char *format, ...)
{
    va_list args;
    va_start(args, format);
    std::string s = vformat(format, args);
    va_end(args);
    HANDLE h = handle_for_ostream(ostrm);
    if (h == INVALID_HANDLE_VALUE)
    {
        return;
    }
    DWORD dwNumberOfCharsWrite;
    if (GetFileType(h) != FILE_TYPE_CHAR)
    {
        s = utf8_to_cp(s, GetConsoleOutputCP());
        WriteFile(h, s.c_str(), (DWORD)s.size(), &dwNumberOfCharsWrite, NULL);
    }
    else
    {
        std::wstring ws = utf8_to_wide(s);
        WriteConsoleW(h, ws.c_str(), (DWORD)ws.size(), &dwNumberOfCharsWrite,
                      NULL);
    }
}
#ifdef __cpp_char8_t
static inline void dbgout(std::ostream &ostrm, const char8_t *format, ...)
{
    va_list args;
    va_start(args, format);
    std::u8string s = vformat(format, args);
    va_end(args);
    HANDLE h = handle_for_ostream(ostrm);
    if (h == INVALID_HANDLE_VALUE)
    {
        return;
    }
    DWORD dwNumberOfCharsWrite;
    if (GetFileType(h) != FILE_TYPE_CHAR)
    {
        std::string str = char8_to_cp(s, GetConsoleOutputCP());
        WriteFile(h, (const char *)str.c_str(), (DWORD)str.size(),
                  &dwNumberOfCharsWrite, NULL);
    }
    else
    {
        std::wstring ws = char8_to_wide(s);
        WriteConsoleW(h, ws.c_str(), (DWORD)ws.size(), &dwNumberOfCharsWrite,
                      NULL);
    }
}
#endif

class unicode_ostream
{
private:
    std::ostream *m_ostrm;
    UINT m_target_cp;
    bool is_ascii(const std::string &s)
    {
        for (std::size_t i = 0; i < s.size(); i++)
        {
            unsigned char c = (unsigned char)s[i];
            if (c > 0x7f) return false;
        }
        return true;
    }

public:
    unicode_ostream(std::ostream &ostrm, UINT target_cp = CP_ACP)
        : m_ostrm(&ostrm), m_target_cp(target_cp)
    {
    }
    std::ostream &stream() { return *m_ostrm; }
    void stream(std::ostream &ostrm) { m_ostrm = &ostrm; }
    UINT target_cp() { return m_target_cp; }
    void target_cp(UINT cp) { m_target_cp = cp; }
    template <typename T>
    unicode_ostream &operator<<(const T &x)
    {
        std::ostringstream oss;
        oss << x;
        std::string output = oss.str();
        if (is_ascii(output))
        {
            (*m_ostrm) << x;
        }
        else
        {
            (*m_ostrm) << utf8_to_cp(output, m_target_cp);
        }
        return *this;
    }
    unicode_ostream &operator<<(const std::wstring &x)
    {
        (*m_ostrm) << wide_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const wchar_t *x)
    {
        (*m_ostrm) << wide_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const std::string &x)
    {
        (*m_ostrm) << utf8_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const char *x)
    {
        (*m_ostrm) << utf8_to_cp(x, m_target_cp);
        return *this;
    }
#ifdef __cpp_char8_t
    unicode_ostream &operator<<(const std::u8string &x)
    {
        (*m_ostrm) << char8_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const char8_t *x)
    {
        (*m_ostrm) << char8_to_cp(x, m_target_cp);
        return *this;
    }
#endif
    unicode_ostream &operator<<(const std::u16string &x)
    {
        (*m_ostrm) << char16_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const char16_t *x)
    {
        (*m_ostrm) << char16_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const std::u32string &x)
    {
        (*m_ostrm) << char32_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(const char32_t *x)
    {
        (*m_ostrm) << char32_to_cp(x, m_target_cp);
        return *this;
    }
    unicode_ostream &operator<<(
        std::ostream &(*pf)(std::ostream &))  // For manipulators...
    {
        (*m_ostrm) << pf;
        return *this;
    }
    unicode_ostream &operator<<(std::basic_ios<char> &(*pf)(
        std::basic_ios<char> &))  // For manipulators...
    {
        (*m_ostrm) << pf;
        return *this;
    }
};

#define U8(X) ((const char *)u8##X)
#define U16(X) (u##X)
#define U32(X) (U##X)
#define WIDE(X) (L##X)

#endif /* STRCONV_AGAIN_H */
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?