Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/21.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 在编译时获取当前月份索引_C++_Visual C++ - Fatal编程技术网

C++ 在编译时获取当前月份索引

C++ 在编译时获取当前月份索引,c++,visual-c++,C++,Visual C++,我正在尝试将格式为Mmm的\uuu DATE\uuu的月份转换为编译时的数字。我需要它用于gcc和MS VC 2012 我的尝试: template <char C0, char C1, char C2> struct month{}; template<> struct month < 'J', 'a', 'n'> { static const unsigned id = 1; }; template<> struct month < '

我正在尝试将格式为
Mmm
\uuu DATE\uuu
的月份转换为编译时的数字。我需要它用于gcc和MS VC 2012

我的尝试:

template <char C0, char C1, char C2>
struct month{};

template<> struct month < 'J', 'a', 'n'> { static const unsigned id = 1; };
template<> struct month < 'S', 'e', 'p'> { static const unsigned id = 9; };

static const char c0 = __DATE__[0];
static const char c1 = __DATE__[1];
static const char c2 = __DATE__[2];

static const unsigned currId = month<c0, c1, c2>::id;      //this gives error
static const unsigned currId2 = month<'S', 'e', 'p'>::id;  //this is fine
模板
结构月{};
模板结构月份<'J','a','n'>{static const unsigned id=1;};
模板结构月份<'S','e','p'>{static const unsigned id=9;};
静态常量字符c0=_日期__[0];
静态常量字符c1=_日期__[1];
静态常量字符c2=_日期__[2];
static const unsigned currId=month::id//这就产生了错误
static const unsigned currId2=month::id//这很好
给出了MS VC

错误C2970:'month':模板参数'C0':'C0':包含具有内部链接的对象的表达式不能用作非类型参数

但是,这一切都很好

有没有一种方法可以使这项工作跨平台/跨编译器

编辑


我需要一个
编译时常量
,所以中的答案并没有真正的帮助。例如,我需要减去两个日期(当前日期和代码中的某个日期),并在这两个日期之间的差异足够大时给出编译时错误

首先:您确定在编译时需要这个吗?如果运行时是可接受的,那么很容易:


但是远离理智,让我们享受一些编译时的乐趣吧

您在这里使用的是模板,但实际上不需要。你可以使用大量的厄运表达:

static const char c0 = __DATE__[0];
static const char c1 = __DATE__[1];
static const char c2 = __DATE__[2];
static const unsigned int month = (
    c0 == 'J' // Jan Jun Jul
        ? (c1 == 'a' ? 1 : (c2 == 'n' ? 6 : 7))
    : c0 == 'F' ? 2
    : c0 == 'M' // Mar May
        ? (c2 == 'r' ? 3 : 5)
    : c0 == 'A' // Apr Aug
        ? (c1 == 'p' ? 4 : 8)
    : c0 == 'S' ? 9
    : c0 == 'O' ? 10
    : c0 == 'N' ? 11
    : 12
);
免责声明:我只是在头上写下了这一点。现在可以了,但谁知道呢,也许我弄错了

事实上,如果你想获得更多乐趣,我们可以对一些字符使用算术:

static const char c0 = __DATE__[0];
static const char c1 = __DATE__[1];
static const char c2 = __DATE__[2];
static const unsigned int month = (
    c0 == 'J' // Jan Jun Jul
        ? (c1 == 'a' ? 1 : (c2 == 'n' ? 6 : 7))
    : c0 == 'M' // Mar May
        ? (3 + (c2 == 'y') * 2)
    : c0 == 'A' // Apr Aug
        ? (4 + (c1 == 'u') * 4)
    : c0 == 'S' ? 9
    : c0 <= 'F' ? (12 - (c0 - 'D') * 5) // Feb, Dec
    : (11 + 'N' - c0) // Oct, Nov
);
static const char c0=\uuuuu DATE\uuuu[0];
静态常量字符c1=_日期__[1];
静态常量字符c2=_日期__[2];
静态常量无符号整月=(
c0=='J'//1-6-7月
(c1=‘a’?1:(c2=‘n’?6:7))
:c0='M'//3月至5月
?(3+(c2=‘y’)*2)
:c0='A'//Apr-Aug
?(4+(c1=‘u’)*4)
:c0=='S'?9

:c0在这里玩得开心

我的答案需要C++14和一些外部LIB,但证明了C++14中有相当惊人的编译时计算

首先我需要在中介绍。这个类是一个编译时字符串,在中讨论过

然后我需要这是能够编译时间的日期和时间计算

接下来我需要
constepr
实现
std::find

template <class InputIterator, class T>
constexpr
inline
InputIterator
find(InputIterator first, InputIterator last, const T& value)
{
    for (; first != last; ++first)
        if (*first == value)
            break;
    return first;
}
接下来,我需要一个实用程序将
str_const
转换为
int

constexpr
int
str_to_int(const str_const& s)
{
    int r = 0;
    auto i = s.begin();
    for (; i != s.end() && *i == ' '; ++i)
        ;
    for (; i != s.end(); ++i)
    {
        r *= 10;
        r += *i - '0';
    }
    return r;
}
(具有最小的错误检查)

最后,我可以使用这些实用程序将
str\u const
转换为
date::year\u month\u day

// Assume the form used by __DATE__: Mmm dd yyyy
constexpr
date::year_month_day
str_to_year_month_day(const str_const& s)
{
    return str_to_month(s.substr(0, 3))
          /str_to_int(s.substr(4, 2))
          /str_to_int(s.substr(7));
}
我刚刚用下面的
main
执行了所有这些操作,它使用
constexpr
计算所有内容,并使用
static\u assert
确认计算:

int
main()
{
    constexpr auto ymd = str_to_year_month_day(__DATE__);
    using namespace date;
    static_assert(ymd == sep/6/2015, "");
    constexpr auto ymwd = year_month_weekday{ymd};
    static_assert(ymwd == sun[1]/sep/2015, "");
}
我在2015年9月6日编写了这个程序,这恰好是本月的第一个星期日


要做到这一点,您需要gcc或clang。即使是最新的VS-2015,其
constexpr
也不足以在编译时进行这些计算。

C++14允许您使用适当的switch case语句来实现这一点,这比滥用三元条件运算符更容易操作:

static constexpr uint8_t get_month(const char date[])
{
    switch (date[0])
    {
        case 'J':
            if      (date[1] == 'a') return 1;  //Jan
            else if (date[2] == 'n') return 6;  //Jun
            else                     return 7;  //Jul
        case 'M':
            if (date[2] == 'r') return 3;  //Mar
            else                return 5;  //May
        case 'A':
            if (date[1] == 'p') return 4;  //Apr
            else                return 8;  //Aug
        case 'F': return 2;    //Feb
        case 'S': return 9;    //Sep
        case 'O': return 10;   //Oct
        case 'N': return 11;   //Nov
        case 'D': return 12;   //Dec
        default:  return 0;    //Error
    }

您可以像
get\u month(\u日期\u)那样调用它
,或者去掉参数,直接使用
\uuuu DATE\uuuuu

字符串文字不能成为好的模板参数。这个问题有用吗?不幸的是没有,因为我需要编译时间常量才能在另一个模板中使用它……仅供参考,这将在MSVC 2015中编译和运行。他们有一个免费的社区版:谢谢我的答案是编译时,我只是建议这是一件愚蠢的事情,并链接到一个更明智的方式在运行时这样做。哦,我明白了,我的错误…但我不能在模板参数中使用它(与原始问题的信息相同).所以我不能用it@relaxxx您可以在模板中使用它。请参阅我的最新编辑。我已经验证了它在ideone中可以工作,并且它应该可以在任何编译器中工作(因为int是常量,并且只使用基本的算术/条件)我像你一样在你的原始代码中添加了简单的模板,但是在MSVC中出现了这个错误。你能不能共享ideone链接,这样我就可以准确地尝试你的代码?哇,我不知道在constexpr中循环是允许的。整个想法不是为了避免编译时的停顿问题吗?C++11禁止在constexpr中循环。C++14不允许。如果C++14编译器无法在编译时完成循环,它将在运行时执行该函数,除非结果用于构造constexpr对象。在后一种情况下,将导致编译时错误。Nit:constexpr意味着inlineBtw,对于clang,
-fconstexpr steps=N
将编译计算的数量增加到
N
>(默认为1MiB IIRC)@TemplateRex:Re:constexpr意味着内联。是的,我知道。我仍在开发一种风格。我目前最喜欢的是在单独的行中指定
constexpr
inline
。理由:我必须将大量代码移植到Visual Studio。即使在VS-2015上,我发现自己也必须禁用
constexpr
一个宏。当我这样做时,有
inline
可以大大简化端口。
// Assume the form used by __DATE__: Mmm dd yyyy
constexpr
date::year_month_day
str_to_year_month_day(const str_const& s)
{
    return str_to_month(s.substr(0, 3))
          /str_to_int(s.substr(4, 2))
          /str_to_int(s.substr(7));
}
int
main()
{
    constexpr auto ymd = str_to_year_month_day(__DATE__);
    using namespace date;
    static_assert(ymd == sep/6/2015, "");
    constexpr auto ymwd = year_month_weekday{ymd};
    static_assert(ymwd == sun[1]/sep/2015, "");
}
static constexpr uint8_t get_month(const char date[])
{
    switch (date[0])
    {
        case 'J':
            if      (date[1] == 'a') return 1;  //Jan
            else if (date[2] == 'n') return 6;  //Jun
            else                     return 7;  //Jul
        case 'M':
            if (date[2] == 'r') return 3;  //Mar
            else                return 5;  //May
        case 'A':
            if (date[1] == 'p') return 4;  //Apr
            else                return 8;  //Aug
        case 'F': return 2;    //Feb
        case 'S': return 9;    //Sep
        case 'O': return 10;   //Oct
        case 'N': return 11;   //Nov
        case 'D': return 12;   //Dec
        default:  return 0;    //Error
    }