用户定义的文字是在编译时还是在运行时解析?

| 我想知道,因为诸如
ULL
f
等的预定义文字显然在编译时已解析。标准(2.14.8 [lex.ext])似乎没有对此进行定义,但似乎倾向于运行时:   [2.14.8 / 2]   用户定义的文字被视为对文字运算符或文字运算符模板(13.5.8)的调用。至   确定给定的用户定义文字L的调用形式,该文字L具有ud后缀X,文字运算符   使用不合格名称规则在L的上下文中查找其文字后缀标识符为X的字符   查找(3.4.1)。令S为该查找找到的声明集。 S不能为空。   (强调我的) 但是,对我来说,这似乎引入了不必要的运行时开销,因为文字只能附加到在编译时可用的值上,例如
13.37f
\"hello\"_x
(其中
_x
是用户定义的文字)。 然后,我们得到了模板化的用户定义字面量,它从未在标准AFAICS中真正定义过(即,没有给出示例,请证明我是错误的)。该函数是在编译时以某种方式神奇地调用的还是仍在运行时?     
已邀请:
是的,您会收到一个函数调用。但是由于
constexpr
文字运算符函数,函数调用可以是编译时常数表达式。 有关示例,请参见此示例。作为另一个示例,它显示了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
用作常量表达式的格式不正确,以及任何非常量用法在运行时抛出。允许的形式“ 10”计算为各个计算值的常数表达式。 请注意,FDIS并未明确允许从字符串文字中读取内容,但是这没有问题,GCC对此也提供了支持(字符左值引用是一个常量表达式,并且在编译时就知道了字符的值)。 IMO如果if着眼睛,就可以读取FDIS,就像允许这样做一样。   然后,我们得到了模板化的用户定义字面量,它从未在标准AFAICS中真正定义过(即,没有给出示例,请证明我是错误的) 在2.14.8中定义了将文字视为调用文字运算符模板的方式。在13.5.8处可以找到更多示例,这些示例详细说明了字面量运算符函数/函数模板本身。   该函数是在编译时以某种方式神奇地调用的还是仍在运行时? 关键字是函数调用替换。见7.1.5。     
@Johannes S当然是正确的,但是我想清楚地添加一下(因为我面对了这一点),即使对于用户定义的“ 5”字面量,也不会将参数视为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     

要回复问题请先登录注册