Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

gcc c++11 limits for user defined constants and template parameter packs

Tags:

c++

c++11

gcc4.7

I've been playing with user defined constants in gcc 4.7.2 and ran into some sort of size limiting factors which I do not quite understand.

The idea was to define a constexpr operator "" for fixed point decimal type. I want to avoid casting from double but rather parse mantissa and exponent at compilation time using variadic templates. The mantissa parsing proved a bit tricky.

When I enable any of the 3 disabled lines at the bottom of the code below, gcc falls into infinite loop and hangs there. I noticed the same max size for floating point literal and explicit instantiation of the variadic template but slightly larger size for integer literal.

I used command: g++ -std=c++11 -Wall -g -o literal_value literal_value.cpp

Using -ftemplate-depth-128 makes no difference.

#include <iostream>
#include <cstdint>

typedef std::uint64_t value_type;

template<value_type Temp, char... List> struct literal_parser;

template<value_type Temp, char Head, char... List>
struct literal_parser<Temp, Head, List...>
{
    static const value_type value = Head == '.' ?
        literal_parser<Temp, List...>::value :
        literal_parser<Temp * 10 + Head - '0', List...>::value;
};

template<value_type Temp, char Last>
struct literal_parser<Temp, Last>
{
    static const value_type value = Last == '.' ?
        Temp : Temp * 10 + Last - '0';
};

template<char... List>
inline constexpr value_type operator"" _value() noexcept
{
    return literal_parser<0U, List...>::value;
}

int main()
{
    std::cout << "value 1: " << 123456789012345678_value << std::endl;
    std::cout << "value 2: " << 1.23456789012345_value << std::endl;
    std::cout << "value 3: " << literal_parser<0U, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5'>::value << std::endl;

#if 0
    std::cout << "value 4: " << 1234567890123456789_value << std::endl;
    std::cout << "value 5: " << 1.234567890123456_value << std::endl;
    std::cout << "value 6: " << literal_parser<0U, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6'>::value << std::endl;
#endif
}

Is that a bug in gcc or am I missing something?

like image 238
Вова Avatar asked Nov 14 '12 15:11

Вова


1 Answers

I must say that you found some nice corner case that makes compilers crazy :-) For me gcc 4.7.2 and 4.8 crashed during compilation. However clang (top version) compiled whole code fine but was using 2.4GB RAM. The problem seems to be connected to ternaty operator for '.' check. If you remove it and comment real number tests in main() everything compiles fine like a blast.

So answering your question you probably do not miss anything and gcc and clang need to probably revise their implementaion based on your case.

like image 91
Mateusz Pusz Avatar answered Nov 10 '22 12:11

Mateusz Pusz