编译时间类型转换检查(constexpr和用户定义的文字)

Joh*_*erg 7 c++ constexpr c++11

更新:我下面贴我自己的答案 在这里,还有这件事情更长的版本:http://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-defined-文字

题:

我做了一个简单的constexpr用户定义的文字_X是可以获得价值为unsigned long long(这是字面定义用户如何工作的数字:http://en.cppreference.com/w/cpp/language/user_literal),然后我做确保该值适合签名的长整数.

这一切都运行良好(太大的值导致编译错误),但只有当我明确创建一个变量,如

constexpr auto a= 150_X;
Run Code Online (Sandbox Code Playgroud)

相反,我会写一些典型的东西

cout << 150_X << endl;;
Run Code Online (Sandbox Code Playgroud)

测试不在编译时执行.

  • 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;
}
Run Code Online (Sandbox Code Playgroud)

哦,供参考:我用的是gcc4.7.2.

Joh*_*erg 4

自我回答: 我找到了一个完整的解决方案,受到我的问题的评论和其他答案以及其他问题(例如/sf/answers/936902221/ )的启发。

解决方案是使用用户定义文字的模板形式并手动对数字进行求和,将基于已解析的数字的总和乘以 10。

我在这里写了这个自我回答的详细版本:http ://scrupulousabstractions.tumblr.com/post/38460349771/c-11-type-safe-use-of-integer-user-define-literals

template<char... Chars>
int operator"" _steps(){
  return {litparser<0,Chars...>::value};
}
Run Code Online (Sandbox Code Playgroud)

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;
};
Run Code Online (Sandbox Code Playgroud)