基于模板的编译时字符串生成器

问题描述

我正在开发基于 mfc 的 GUI。其中一个控件允许标记语言 (XAML) 在其中呈现文本和图标,因此我正在大量使用它。所有控件的标记字符串几乎相同(一个表单中有 12 个),所以我想知道是否有一种简单的方法来制作一个生成该字符串的函数

所以控件是预定义的并且在执行过程中不会改变,我想在编译时生成这些字符串,以及如果它们是直接键入然后编译的。

我正在使用 boost::hana,但我无法通过我尝试过的任何方式在模板中使用字符串文字。我知道由于编译时内存分配未知,无法在模板中直接使用字符串文字

除了在结构中使用 externstatic 分配的经典技巧之外,由于增加了语法复杂性,我不喜欢 C++17(或更低版本,但不是 c ++20 请)允许这样做?

注意 - 一个额外的应该是在不使用宏的函数中直接格式化 int(使用 10 而不是“10”)。

接下来是代码,当然,它不会以当前形式编译:

#include <iostream>
#include <boost/hana/string.hpp>
namespace hana = boost::hana;

constexpr auto markup1()
{
    return (BOOST_HANA_STRING(R"(<Border Padding='4' BorderThickness='2' BorderBrush='#767676' Background='#e4ecf7'>
            <StackPanel TextBlock.FontFamily='Tahoma'>
            <Border Margin='4' Padding='4' Background='#FF212C'><TextBlock HorizontalAlignment='Center' Foreground='#ffffff' FontSize='24' FontWeight='Bold'>)") +

        BOOST_HANA_STRING("USERS") +

        BOOST_HANA_STRING(R"(</TextBlock></Border>
            <TextBlock Padding='9,6,30,7' FontWeight='Bold' textwrapping='Wrap'>)") +

        BOOST_HANA_STRING("User Management. Allows creation of administrators and users.") +

        BOOST_HANA_STRING(R"(</TextBlock>
            <Border Height='1' Background='#9ebbdd'/>
            <Border Height='1' Background='White'/>
            <Image Source=')") +

        BOOST_HANA_STRING("10") + 

        BOOST_HANA_STRING(R"(' Margin='10' VerticalAlignment='Center'/>
            </StackPanel>
            </Border>)") ).c_str();
}

template <const char* header,const char* description,const char* image>
constexpr auto markup2()
{
    return (BOOST_HANA_STRING(R"(<Border Padding='4' BorderThickness='2' BorderBrush='#767676' Background='#e4ecf7'>
            <StackPanel TextBlock.FontFamily='Tahoma'>
            <Border Margin='4' Padding='4' Background='#FF212C'><TextBlock HorizontalAlignment='Center' Foreground='#ffffff' FontSize='24' FontWeight='Bold'>)") +

        BOOST_HANA_STRING(header) +

        BOOST_HANA_STRING(R"(</TextBlock></Border>
            <TextBlock Padding='9,7' FontWeight='Bold' textwrapping='Wrap'>)") +

        BOOST_HANA_STRING(description) +

        BOOST_HANA_STRING(R"(</TextBlock>
            <Border Height='1' Background='#9ebbdd'/>
            <Border Height='1' Background='White'/>
            <Image Source=')") +

        BOOST_HANA_STRING(image) + 

        BOOST_HANA_STRING(R"(' Margin='10' VerticalAlignment='Center'/>
            </StackPanel>
            </Border>)") ).c_str();
}

int main()
{
    std::string str1 { markup1() };
    std::string str2 { markup2<"USERS","User Management. Allows creation of administrators and users.","10">() };
    
    std::cout << std::boolalpha << (str1 == str2); 
}

可以直接访问coliru:http://coliru.stacked-crooked.com/a/4a5bc326be33cb3e

解决方法

将字符串文字直接作为模板参数传递是不合法的,永远;但是,您可以将字符串文字绑定到一个 int WINAPI _tWinMain(HINSTANCE,HINSTANCE,LPTSTR argv,int argc) { try { Application->Initialize(); Application->CreateForm(__classid(TFormMain),&FormMain); if (argc > 1) { // pass argv to app. } Application->Run(); } catch (Exception &exception) { Application->ShowException(&exception); } catch (...) { try { throw Exception(""); } catch (Exception &exception) { Application->ShowException(&exception); } } return 0; } 数组并传递它(通过引用):

constexpr

Online Demo

当然,在预先编写一些样板之后,C++20 有多个选项可以使这更漂亮一些。

,

您可以将 HANA_STRING 作为“常规”(需要是模板)参数:

template <typename Header,typename Description,typename Image>
constexpr auto markup2(Header header,Description description,Image image)
{
    return (BOOST_HANA_STRING(
R"(<Border Padding='4' BorderThickness='2' BorderBrush='#767676' Background='#e4ecf7'>
<StackPanel TextBlock.FontFamily='Tahoma'>
<Border Margin='4' Padding='4' Background='#FF212C'>
<TextBlock HorizontalAlignment='Center' Foreground='#ffffff' FontSize='24' FontWeight='Bold'>)")

    + header
    + BOOST_HANA_STRING(
R"(</TextBlock></Border>
<TextBlock Padding='9,6,30,7' FontWeight='Bold' TextWrapping='Wrap'>)")

    + description
    + BOOST_HANA_STRING(
R"(</TextBlock>
<Border Height='1' Background='#9ebbdd'/>
<Border Height='1' Background='White'/>
<Image Source=')")

    + image

    + BOOST_HANA_STRING(
R"(' Margin='10' VerticalAlignment='Center'/>
</StackPanel>
</Border>)") ).c_str();
}

调用类似于

std::string str2 { markup2(
    BOOST_HANA_STRING("USERS"),BOOST_HANA_STRING("User Management. Allows creation of administrators and users."),BOOST_HANA_STRING("10")) };

Demo

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...