首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TODO提醒警员

TODO提醒警员
EN

Stack Overflow用户
提问于 2017-11-17 21:11:09
回答 1查看 162关注 0票数 2

我看到一个家伙创建了一个类似于static_assert的东西,它使用DATE来创建一个TODO代码部分,我喜欢这个想法,所以我试着实现它,当我的编译器不喜欢我的近似时,问题就出现了,它说:

  1. 太复常数函数
  2. 表达式应具有常量值

在启用c++17功能的情况下,我使用Visual 2017,关键字CONSTEXPR是一个宏,如果编译器支持该宏,则该宏的精度与constexpr相同。

代码:

代码语言:javascript
复制
namespace private_TODO
{
CONSTEXPR bool is_digit(char c)
{
    return c <= '9' && c >= '0';
}

CONSTEXPR unsigned stoi_impl(const char* str, int rec = 0, int value = 0)
{
    return rec != 0 ?
        is_digit(*str) ?
        stoi_impl(str + 1, rec--, (*str - '0') + value * 10)
        : throw "Compile-time-error: not a digit"
        : value;
}

CONSTEXPR unsigned stoi(const char* str, int maxIter)
{
    return stoi_impl(str, maxIter);
}

CONSTEXPR unsigned year(const char* str)
{
    return stoi(str, 4);
}

CONSTEXPR bool str_cmp(const char* str, const char* str2, unsigned sz)
{
    return sz != 0 ?
        *str == *str2 ? str_cmp(str + 1, str2 + 1, --sz)
            : false
        : true;
}

CONSTEXPR unsigned month(const char* str)
{
    return str_cmp(str, "Jan", 3) ? 1 :
        str_cmp(str, "Feb", 3) ? 2 :
        str_cmp(str, "Mar", 3) ? 3 :
        str_cmp(str, "Apr", 3) ? 4 :
        str_cmp(str, "May", 3) ? 5 :
        str_cmp(str, "Jun", 3) ? 6 :
        str_cmp(str, "Jul", 3) ? 7 :
        str_cmp(str, "Aug", 3) ? 8 :
        str_cmp(str, "Set", 3) ? 9 :
        str_cmp(str, "Oct", 3) ? 10 :
        str_cmp(str, "Nov", 3) ? 11 :
        str_cmp(str, "Dec", 3) ? 12 :
        throw "Compile-time error: Not a month!";
}

CONSTEXPR unsigned day(const char* str)
{
    return stoi(str, 2);
}

CONSTEXPR unsigned str_size(const char* str, unsigned value = 0)
{
    return *str != 0 ?
        str_size(str++, value++)
        : value;
}

CONSTEXPR unsigned total(const char* str)
{
    return (str_size(str) == 11 && str[3] == ' ' && str[6] == ' ') ?
        year(str + 7) * 512 + month(str) * 32 + day(str + 4)
        : throw "invalid string";
}
}

#define TODO(DATE, MESSAGE)\
static_assert(::private_TODO::total(__DATE__) < ::private_TODO::total(DATE), MESSAGE)
void test()
{
    TODO("NOV 16 2017", "THIS SHOULD THROW"); //11/16/17 is when I tested
}

我不明白为什么说表达式应该有恒定的值,因为我认为所有的东西都是常数,是的,它们是复杂的函数,我希望有人能帮助我降低这个函数的复杂度。

编辑:其中一个错误来自str_size,它说不能将其计算为常量。

我终于用string_view类实现了它。

代码语言:javascript
复制
using namespace std::string_literals;
using namespace std::string_view_literals;
/* TODO reminders */
namespace private_TODO
{
CONSTEXPR bool is_digit(char c)
{
    return c <= '9' && c >= '0';
}


CONSTEXPR unsigned stoi_impl(const std::string_view& str, int value = 0)
{
    return str.size() != 0 ?
        is_digit(str[0]) ?
        stoi_impl(str.substr(1, str.size() - 1), (str[0] - '0') + value * 10)
        : throw "Compile-time-error: not a digit"
        : value;
}

CONSTEXPR unsigned stoi(const std::string_view& str)
{
    return stoi_impl(str);
}

CONSTEXPR bool str_cmp(const std::string_view& str, const std::string_view& str2, unsigned sz = 0)
{
    return sz != str.size() ?
        str[sz] == str2[sz] ?
        str_cmp(str, str2, ++sz)
        : false
        : true;
}

CONSTEXPR unsigned month(const std::string_view& str)
{
    return 
        str_cmp(str, "Jan"sv) ? 1 :
        str_cmp(str, "Feb"sv) ? 2 :
        str_cmp(str, "Mar"sv) ? 3 :
        str_cmp(str, "Apr"sv) ? 4 :
        str_cmp(str, "May"sv) ? 5 :
        str_cmp(str, "Jun"sv) ? 6 :
        str_cmp(str, "Jul"sv) ? 7 :
        str_cmp(str, "Aug"sv) ? 8 :
        str_cmp(str, "Set"sv) ? 9 :
        str_cmp(str, "Oct"sv) ? 10 :
        str_cmp(str, "Nov"sv) ? 11 :
        str_cmp(str, "Dec"sv) ? 12 :
        throw "Compile-time error: Not a month!";
}

CONSTEXPR unsigned total(const std::string_view& str)
{
    return (str.size() == 11 && str[3] == ' ' && str[6] == ' ') ?
        stoi(str.substr(7, 4)) * 512 + month(str.substr(0, 3)) * 32 + stoi(str.substr(4, 2))
        : throw "invalid string";
}
}
#define TODO(DATE, MESSAGE)\
static_assert(::private_TODO::total(std::string_view(__DATE__, 11)) < ::private_TODO::total(DATE ## sv), MESSAGE)
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-17 21:23:14

constexpr必须在递归的有限数之后进行计算。你的职能

代码语言:javascript
复制
constexpr bool str_cmp(const char* str, const char* str2, unsigned sz)
{
    return sz != 0 ?
        *str == *str2 ? str_cmp(str + 1, str2 + 1, sz--)
            : false
        : true;
}

constexpr unsigned str_size(const char* str, unsigned value = 0)
{
    return *str != 0 ?
        str_size(str++, value++)
        : value;
}

不要。相反,它们构成无限递归和不受限制的访问。的返回值,即传递给递归的值。

代码语言:javascript
复制
sz--
str++
value++

与输入相同。正确是

代码语言:javascript
复制
constexpr bool str_cmp(const char* str1, const char* str2, unsigned size)
{
  return size==0 || (*str1 == *str2 && str_cmp(++str1,++str2,--size));
}

constexpr unsigned str_size(const char* str, unsigned value = 0)
{
  return *str? str_size(++str,++value) : value;
}

不过,这可能不是您代码中唯一的错误。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47359335

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档