在编译时获取当前月份索引 [英] Get current month index in compile time

查看:126
本文介绍了在编译时获取当前月份索引的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图将 __ DATE __ 的格式 Mmm 转换为编译时的数字。我需要它为gcc和MS VC 2012。



我的尝试:

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

模板<> struct month< 'J','a','n'> {static const unsigned id = 1; };
模板<> 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; //这是罚款

在MS VC中提供



错误C2970:'月':模板参数'C0':'C0':涉及与内部连接的对象表达式不能被用作非类型参数



但在 ideone 上可以正常工作。

$



编辑是否有办法使这项工作成为跨平台/编译器?

我需要一个编译时常所以的类似问题没有真正的帮助。我需要例如减去两个日期(目前在一些代码为准),并给编译时错误时,这两个相差足够大。

解决方案

首先:你确定在编译时需要这个吗?如果运行时是可以接受的,很容易: http://www.keil.com/support/ docs / 1102.htm






但是摆脱某些事情,让我们有一些编译时间的乐趣!



你在这里使用模板,但你真的不需要。你可以使用庞大的doom表达式:

  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'// 4月8月
?(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'? - (c0 - 'D')* 5)// Feb,Dec
:(11 +'N'-c0)// Oct,Nov
);

*:byfun我的意思是: / p>

由于这些是const,你可以使用它与模板。例如,假设我们已经有了在十一月从而结束了合同的工作,我们要相信我们会以高速率得到带回在几天后一切都结束了:

  #include< iostream> 
using namespace std;

static const unsigned int month = ...;

template< int n> class mm {
public:
static int v;
};

模板<> int mm 9 :: v = 3; // still employ
template<> int mm 10 :: v = 2; //让我们不要太可疑
template<> int mm 11:v = 1; // patience ...
// 12月没有价值 - 繁荣!我们在钱!圣诞节的时候!

int main(){
std :: cout< mm< month> :: v;
return 0;
}

最后,如果你不想乱丢全局范围,应使用constexpr功能:

 静态constexpr INT得到月(无效){
为const char C0 = __DATE __ [0] ;
const char c1 = __DATE __ [1];
const char c2 = __DATE __ [2];
return(
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'// 4月8月
?(c1 =='p'?4:8)
:c0 =='S'?9
:c0 ==' ?10
:c0 =='N'?11
:12
);
}

...

std :: cout< mm< getMonth()> :: v;


I'm trying to convert month from __DATE__ in format Mmm to number in compile time. I need it for gcc and MS VC 2012.

my attempt:

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

gives in MS VC

error C2970: 'month' : template parameter 'C0' : 'c0' : an expression involving objects with internal linkage cannot be used as a non-type argument

but on ideone works fine.

Is there a way to make this work cross platform/compiler?

edit

I need a compile-time constant So answers in similar question doesn't really help. I need to for example subtract two dates (current and some date in code) and give compile time error when difference between those two is large enough.

解决方案

First: are you sure you need this at compile-time? If run-time is acceptable it's easy: http://www.keil.com/support/docs/1102.htm


But moving away from what's sane, let's have some compile-time fun!

You're using templates here but you really don't need to. You can use a massive expression of doom instead:

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
);

Disclaimer: I just wrote that off the top of my head. It works now, but who knows, maybe I got March wrong.

In fact if you want to get even more fun* we can use arithmetic on some characters:

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
);

*: by "fun" I mean: hated by other developers

Since these are const, you can then use it with templates. For example, suppose we've got a contract job which ends in November, and we want to be sure we'll get brought back in for a few days at a high rate once it's over:

#include <iostream>
using namespace std;

static const unsigned int month = ...;

template <int n> class mm {
public:
    static int v;
};

template<> int mm<9>::v=3; // still employed
template<> int mm<10>::v=2; // let's not be too suspicious
template<> int mm<11>::v=1; // patience...
// no value for December - boom! we're in the money! Just in time for Christmas!

int main() {
    std::cout << mm<month>::v;
    return 0;
}

Finally, if you don't want to be littering the global scope, you should use a constexpr function:

static constexpr int getMonth( void ) {
    const char c0 = __DATE__[0];
    const char c1 = __DATE__[1];
    const char c2 = __DATE__[2];
    return (
        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
    );
}

...

std::cout << mm<getMonth()>::v;

这篇关于在编译时获取当前月份索引的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆