编译时类型转换检查(constexpr和用户定义的文字)
Compile time type conversion check (constexpr and user defined literals)
更新:我在下面发布了自己的答案这里有一个更长的版本:http://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-literals
问题:
我制作了一个简单的constexpr
用户定义的文字_X
,它将值作为无符号长-长(这就是数字用户定义文字的工作方式:http://en.cppreference.com/w/cpp/language/user_literal),然后我确保该值适合有符号的长-长。
这一切都很好(值太大会导致编译错误),但只有当我显式创建一个变量(如)时
constexpr auto a= 150_X;
如果我写一些典型的东西,比如
cout << 150_X << endl;;
测试不是在编译时执行的。
如果constexpr函数被分配给constexpr变量,那么它们是否只在编译时执行?(我在标准中找不到)
有可能实现我正在寻找的
_X
的安全行为吗?
完整示例:
#include<iostream>
#include<stdexcept>
inline constexpr long long testConv(unsigned long long v) {
return (v > 100 ) ? throw std::exception() : v;
} // will eventually use actual limit from numeric_limits
inline constexpr long long operator "" _X(unsigned long long f) {
return testConv(f) ;
}
int main(){
constexpr auto a= 5_X;
std::cout << a << std::endl;
std::cout << 200_X << std::endl; // This bad literal is accepted at compile time
constexpr auto c=250_X; // This bad literal is not accepted at compile time
std::cout << c << std::endl;
}
哦,作为参考:我使用了gcc4.7.2。
自我回答: 我找到了一个完整的解决方案,灵感来自对我的问题的评论和其他答案,以及其他问题,如https://stackoverflow.com/a/13384317/1149664.
解决方案是使用用户定义的文字的模板形式,手动求和,将基于已解析数字的和乘以10。
我在这里写了一个详细的自我回答:http://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-literals
template<char... Chars>
int operator"" _steps(){
return {litparser<0,Chars...>::value};
}
Litparser是一个小型模板元程序,它将字符列表作为从Chars参数包中的输入字符扩展而来的参数。
typedef unsigned long long ULL;
// Delcare the litparser
template<ULL Sum, char... Chars> struct litparser;
// Specialize on the case where there's at least one character left:
template<ULL Sum, char Head, char... Rest>
struct litparser<Sum, Head, Rest...> {
// parse a digit. recurse with new sum and ramaining digits
static const ULL value = litparser<
(Head <'0' || Head >'9') ? throw std::exception() :
Sum*10 + Head-'0' , Rest...>::value;
};
// When 'Rest' finally is empty, we reach this terminating case
template<ULL Sum> struct litparser<Sum> {
static const ULL value = Sum;
};
constexpr
函数可以在编译时执行;也就是说,它们符合在常量表达式中使用的条件。如果它们不用于常量表达式,那么在编译时执行它们就没有意义,尽管我认为这是允许的。
由于不允许将参数声明为constexpr
(第7.1.5/1节)[1],我不认为有任何方法可以在编译时强制评估operator "" _X(unsigned long long)
,但您可能可以使用template<char...> operator "" _X()
如果在常量表达式中调用constexpr
函数,则参数将是常量表达式(如果不是,则调用不是常量表达式)。但是,不能通过将参数声明为constexpr
来强制调用为常量表达式,因为不允许将参数声明为constexpr
,请参阅对标准的引用。
[注1]:感谢@LightnessRacesInOrbit搜索标准来证明第二段中的声明。
Constexpr函数不需要在编译时执行。但是你的目标是可以实现的。为了更好地理解这个问题,并举例说明如何创建一个总是在编译时评估的迭代,我推荐这篇文章。
- 创建一个函数以在输入为负数或零时输出字符串.第一次执行用户定义的函数
- 使用用户定义函数的字符串反转
- 用户定义函数中的指针和输入
- Visual C++(VS2017)中用户定义的转换不明确
- 使用用户定义的参数调用future/async并调用类方法
- 带有用户定义类的c++折叠表达式
- g++用户定义的动态链接库上的全局new和delete运算符
- 直接在 unordered_map 的方法中使用哈希,而不是生成哈希的用户定义对象
- 修改"std::set"中用户定义类型的值
- 参数包构造函数在类模板中隐藏用户定义的转换
- MAKE:找不到包含的用户定义的头文件?
- C++:用户定义的显式类型转换函数错误
- 是否有解决方法可以在 c++ 中为 short 定义用户定义的文字?
- 从 QAbstractItemModel 返回自定义用户类型
- 无法引用自定义用户控件
- Lua:为自定义用户数据提供一个字符串方法
- 是否可以在visualstudio调试窗口中定义用户定义的变量
- 如何在编写自定义用户操作时引用内置操作
- C++自定义用户输入调用变量
- 不能定义用户定义的字面值