我想知道,因为ULL
,f
等预定义文字在编译时显然得到了解决。标准(2.14.8 [lex.ext])似乎没有定义这个,但似乎倾向于运行时:
[2.14.8 / 2]
用户定义的文字被视为对文字运算符或文字运算符模板的调用(13.5.8)。至 使用ud-suffix X确定给定用户定义文字L的此调用的形式,即literal-operator-id 其文字后缀标识符为X,使用非限定名称规则在L的上下文中查找 查找(3.4.1)。设S是此查找找到的声明集。 S不得为空 (强调我的。)
但是,对我而言,这似乎会引入不必要的运行时开销,因为文字只能附加到编译时可用的值,例如13.37f
或"hello"_x
(其中_x
}是用户定义的文字)
然后,我们得到了模板化的用户定义文字,它从未真正在标准AFAICS中定义(即,没有给出示例,请证明我的错误)。该函数是否在编译时以某种方式神奇地调用,或者它仍然是运行时?
答案 0 :(得分:7)
是的,你得到一个函数调用。但是由于constexpr
文字运算符函数,函数调用可以是编译时常量表达式。
有关示例,请参阅this one。作为显示FDIS允许的constexpr
计算的高级形式的另一个例子,你可以编译时间基数为26的文字
typedef unsigned long long ull;
constexpr ull base26(char const *s, ull ps) {
return (*s && !(*s >= 'a' && *s <= 'z')) ? throw "bad char!" :
(!*s ? ps : base26(s + 1, (ps * 26ULL) + (*s - 'a')));
}
constexpr ull operator "" _26(char const *s, std::size_t len) {
return base26(s, 0);
}
说"bcd-"_26
将评估throw-expression,从而使返回值变为非常量。反过来,它导致任何使用"bcd-"_26
作为常量表达式变得格式不正确,以及任何非常量用法在运行时抛出。允许的形式"bcd"_26
求值为相应计算值的常量表达式。
请注意,FDIS没有明确允许从字符串文字读取,但它没有问题,GCC支持这一点(字符左值引用是一个常量表达式,字符的值在编译时是已知的)。国际海事组织,如果一个人眯着眼睛,就可以读取FDIS,好像这是允许的。
然后,我们得到了模板化的用户定义文字,它从未真正在标准AFAICS中定义(即,没有给出示例,请证明我错了)
2.14.8中定义了将文字处理为调用文字运算符模板。您可以在13.5.8找到更多关于文字运算符函数/函数模板本身详细信息的示例。
该函数是否在编译时以某种方式神奇地调用,还是仍然是运行时?
关键字是函数调用替换。见7.1.5。
答案 1 :(得分:0)
constexpr
用户定义的文字,也不考虑参数 constexpr或编译时间常量,例如,它们不能用作模板的整数常量。
此外,只有这样的事情实际上会给出编译时评估:
inline constexpr long long _xx(unsigned long long v) {
return (v > 100 ) ? throw std::exception() : v;
}
constexpr auto a= 150_xx;
所以,那将无法编译。但这会:
cout << 150_xx << endl;
以下是不允许的:
inline constexpr long long _xx(unsigned long long v) {
return some_trait<v>::value;
}
这很烦人,但考虑到(其他)constexpr函数在执行期间也可以被调用,这很自然。
对于整数用户定义的文字,只有可以通过使用模板表单强制执行编译时处理。我的问题和自我回答中的示例:https://stackoverflow.com/a/13869688/1149664