C++ gcc c&x2B+;11用户定义常数和模板参数包的限制

C++ gcc c&x2B+;11用户定义常数和模板参数包的限制,c++,c++11,gcc4.7,C++,C++11,Gcc4.7,我一直在玩GCC4.7.2中的用户定义常量,遇到了一些我不太理解的大小限制因素 其思想是为定点十进制类型定义一个constexpr运算符“”。我希望避免从双精度转换,而是在编译时使用可变模板解析尾数和指数。尾数解析证明有点棘手 当我启用下面代码底部的3个禁用行中的任意一行时,gcc会陷入无限循环并挂起。我注意到浮点文本和变量模板的显式实例化的最大大小相同,但整数文本的大小稍大 我使用命令:g++-std=c++11-Wall-g-o literal\u value literal\u value

我一直在玩GCC4.7.2中的用户定义常量,遇到了一些我不太理解的大小限制因素

其思想是为定点十进制类型定义一个constexpr运算符“”。我希望避免从双精度转换,而是在编译时使用可变模板解析尾数和指数。尾数解析证明有点棘手

当我启用下面代码底部的3个禁用行中的任意一行时,gcc会陷入无限循环并挂起。我注意到浮点文本和变量模板的显式实例化的最大大小相同,但整数文本的大小稍大

我使用命令:g++-std=c++11-Wall-g-o literal\u value literal\u value.cpp

使用-ftemplate-depth-128没有区别

#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
}
#包括
#包括
typedef std::uint64_t value_type;
模板结构文本解析器;
模板
结构字面值分析器
{
静态常量值\u类型值=头=''?
文字解析器::值:
文本解析器::值;
};
模板
结构字面值分析器
{
静态常量值\u类型值=Last=''?
温度:温度*10+最后一个-'0';
};
模板
内联constexpr value_类型运算符“”_value()无异常
{
返回literal_parser::value;
}
int main()
{

std::cout我认为问题在于如何编写命令

g++ -std=c++11 -Wall -g -o literal_value literal_value.cpp
永远不要把源文件放在末尾可能是个好主意,事实上,在Windows下的MinGW下使用g++4.7.2可以很好地编译

g++ -std=c++11 -Wall -g literal_value.cpp -o literal_value

一般来说,保留行的最后一部分用于链接规范是个好主意。

我必须说,您发现了一些让编译器疯狂的好例子:-)对于我来说,gcc 4.7.2和4.8在编译过程中崩溃了。但是,clang(顶级版本)编译的整个代码很好,但使用的是2.4GB RAM。问题似乎与“.”的ternaty运算符有关。请检查。如果删除它并在main()中注释实数测试,则一切编译都很好


因此,回答您的问题时,您可能不会遗漏任何内容,gcc和clang可能需要根据您的案例修改它们的实现。

根据Mateusz的回答,我使用constexpr函数重新定义了文字解析器模板来解析单个数字,现在一切看起来都很完美。非常感谢您的帮助

#include <iostream>
#include <cstdint>

typedef std::uint64_t value_type;

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

inline constexpr value_type parse_digit(value_type value, char digit) noexcept
{
    return digit == '.' ? value : value * 10 + digit - '0';
}

template<value_type Temp, char Head, char... List>
struct literal_parser<Temp, Head, List...>
{
    static const value_type value =
        literal_parser<parse_digit(Temp, Head), List...>::value;
};

template<value_type Temp, char Last>
struct literal_parser<Temp, Last>
{
    static const value_type value = parse_digit(Temp, Last);
};

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;

    std::cout << "value 4: " << 1234567890123456789_value << std::endl;
    std::cout << "value 5: " << 1.2345678901234567890_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;
}
#包括
#包括
typedef std::uint64_t value_type;
模板结构文本解析器;
内联constexpr值\类型解析\数字(值\类型值,字符数字)无异常
{
返回数字=='。?值:值*10+数字-'0';
}
模板
结构字面值分析器
{
静态常量值\u类型值=
文本解析器::值;
};
模板
结构字面值分析器
{
静态常量值\类型值=解析\位(临时,最后);
};
模板
内联constexpr value_类型运算符“”_value()无异常
{
返回literal_parser::value;
}
int main()
{
std::cout
static const value_type value=Head=='?
文字解析器::值:
文本解析器::值;

这将使编译时间完全爆炸,因为编译器必须计算条件的两侧(使整个过程在位数上呈指数增长)。尝试将表达式更改为类似于
literal\u parser::value

据我所知,自定义非字符串文本在gcc 4.7中还不起作用。不过,自定义字符串文本似乎工作正常。值得一提的是,我在gcc 4.7.2中遇到了同样的问题。很高兴知道,我不是唯一一个在解决这个问题的人。谢谢。我很高兴我在表中检查了这些功能的状态。可变模板N2242是用户定义的文字N2765是现在我发现编译器在与这些模板斗争时会消耗我linux机器上的所有内存。机器上有4G和2.5G可用于gcc。这似乎是任务的内存消耗过多。它编译f我使用的是G++4.7版的ine…但需要将近9GB的内存。您可能耗尽了内存并开始交换。它“仅”使用8.1GB的G++从主干(即4.8版),这是一个小小的改进:-\n我想你弄错了。根据POSIX,所有非选项命令行参数都应该遵循可选参数。GNU程序通常允许重新排序,但这是一个扩展。就我个人而言,我总是使用源代码编译,并在最后链接到目标文件,因为这是一种可移植的方式,可以在th gcc、Sun CC和其他编译器。@MaximYegorushkin我能说的是第一个命令不起作用,第二个命令起作用,我也一直看到有人用这种方式排列gcc命令,我总是觉得这是一个非常好和干净的主意。你应该按照解析符号所需的顺序列出对象/库,但对于其他选项ons(包括本例中的所有选项)没有区别,与OP的问题无关。
static const value_type value = Head == '.' ?
    literal_parser<Temp, List...>::value :
    literal_parser<Temp * 10 + Head - '0', List...>::value;