c++visual-studio-2017c++17boost-hana

Compiler fails due to recursion in MSVS2017


I am using compile time features of boost::hana::string for generating xaml markup strings for a GUI.

I am using VS2017 configured as C++17 language, but there is some moment where strings are too long that I received the next message from compiler:

 fatal error C1202: recursive type or function dependency context too complex

If I delete a few characters from the string, everything is ok, so I guess is length dependant.

Next code is working right in coliru under gcc, but it fails miserabily in MSVS2017:

NOTE: Please, take into account that I have removed all the configurabled and templated variables in the example to focus just in the problem. Of course, it is not worthy to use boost::hana like sample code, is just a minimal working source.

#include <boost/hana/string.hpp>

constexpr auto markup_ribbon()
{
    return (BOOST_HANA_STRING(
        "<?xml version='1.0' encoding='iso-8859-1'?>"
        "<Border VerticalAlignment='Top'>"
        "<Border.Background>"
            "<LinearGradientBrush StartPoint='0,0.2' EndPoint='0.8,0.8'>"
                "<GradientStop Offset='0' Color='#cd0000'/>"
                "<GradientStop Offset='0.75' Color='#fc999e'/>"
                "<GradientStop Offset='1' Color='#e4ecf7'/>"
            "</LinearGradientBrush>"
        "</Border.Background>"
        "<StackPanel Orientation='Vertical' TextBlock.FontFamily='Tahoma'>"
            "<StackPanel.Resources>"
                "<Style TargetType='Path'>"
                    "<Setter Property='Fill' Value='Blue'/>"
                    "<Style.Triggers>"
                        "<Trigger Property='IsMouseOver' Value='True'>"
                            "<Trigger.Setters>"
                                "<Setter Property='Fill' Value='Red'/>"
                            "</Trigger.Setters>"
                        "</Trigger>"
                    "</Style.Triggers>"
                "</Style>"
            "</StackPanel.Resources>"
            "<Grid>"
                "<Grid.ColumnDefinitions>"
                    "<ColumnDefinition Width='300'/>"
                    "<ColumnDefinition Width='*'/>"
                    "<ColumnDefinition Width='*'/>"
                    "<ColumnDefinition Width='50'/>"
                    "<ColumnDefinition Width='200'/>"
                "</Grid.ColumnDefinitions>"
                "<Image Margin='10' HorizontalAlignment='Left' VerticalAlignment='Center' Source='1'/>"
                "<TextBlock Grid.Column='1' HorizontalAlignment='Left' VerticalAlignment='Center' FontSize='44' FontWeight='Bold' Foreground='#ffffff'>ASDF2021</TextBlock>"
                "<Image Grid.Column='2' HorizontalAlignment='Left' VerticalAlignment='Top' Source='3'/>"
                "<TextBlock Grid.Column='3' HorizontalAlignment='Right' VerticalAlignment='Center'><Hyperlink TextDecorations='' Tag='back' ToolTip='Back to administration screen. Back to administration screen.'><Path Stroke='Purple' StrokeThickness='2' Data='M12.981,9.073V6.817l-12.106,6.99l12.106,6.99v-2.422c3.285-0.002,9.052,0.28,9.052,2.269c0,2.78-6.023,4.263-6.023,4.263v2.132c0,0,13.53,0.463,13.53-9.823C29.54,9.134,17.952,8.831,12.981,9.073z'/></Hyperlink></TextBlock>"
                "<TextBlock Grid.Column='4' Margin='0,0,30,0' HorizontalAlignment='Right' VerticalAlignment='Center' FontSize='18' FontWeight='Bold'><Hyperlink Tag='exit' TextDecorations='' ToolTip='Close current session and go back to user screen. Good Bye, good bye.'>Close current session</Hyperlink></TextBlock>"
            "</Grid>"
            "<Border Height='3' Background='#9ebbdd'/>"
            "<Border Height='3' Background='White'/>"
        "</StackPanel>"
        "</Border>")
        ).c_str();
}

#include <iostream>

constexpr auto markup = markup_ribbon();

int main()
{
    std::cout << markup << std::endl;
}

I understand that problem is compiler+recursion related, not boost::hana's problem at all, but maybe is there some tweak, hack or something that I may adjust in IDE so this works?


Solution

  • The compiler is giving up because you are creating a template with too many parameters. The representation of a Hana string is hana::string<'<', '?', 'x', 'm',...> where each character is a non-type template parameter. This is generated by some tricks inside the BOOST_HANA_STRING macro.

    I suggest looking at the following presentation for some insight on how to deal with large compile-time strings: Constexpr All the Things - Jason Turner, Ben Deane

    Aside from that, here is a basic example of one possible approach that you could possibly put in your own macro depending on how you are using these.

    static constexpr char name[] = "really long string";
    
    template <char const* str>
    struct my_string {
        static constexpr char const* value = str;
    };
    
    auto name_s = my_string<name>{};
    
    static_assert(name_s.value[3] == 'l', "");