什么是对常数算法的编译时评估的处理,它可以在预处理器中完成吗?

时间:2010-03-11 07:53:41

标签: c++ c

template <int T>
void aFunc(){}

int main()
{

    int anArray[45-32];

    switch(4)
    {
    case 4<45:
        break;
    }
    aFunc<4*3/7&8 == 45 - 5>();
}

所以这一切都在VC ++ 2005中编译

是这个标准吗?如果是这样,条件运算符返回什么? 0和1?有限制吗?

和我最感兴趣的东西,你能用宏来做吗?定义?

编辑:

进一步详细说明预处理器位:

#define STRINGAFY(n)     #n
#define STRINGAFY_2(n)   STRINGAFY(n)

#define SOME_RANDOM_MACRO(n)     n


printf("%s", STRINGAFY(1));  //prints out "1"
printf("%s", STRINGAFY(SOME_RANDOM_MACRO(1)));  //prints out "SOME_RANDOM_MACRO(1)"
printf("%s", STRINGAFY_2(SOME_RANDOM_MACRO(1)));  //causes SOME_RANDOM_MACRO to be evaluated and prints out "1"
printf("%s", STRINGAFY_2(1+1)); // doesn't evaluate and print "2", prints "1+1" :(

5 个答案:

答案 0 :(得分:7)

  

是这个标准吗?

是。这些被称为"constant expressions"。 (另请参阅C ++标准中的5.19 [expr.const]。)

  

如果是这样,条件运算符返回什么? 0和1?有限制吗?

falsetrue,可以隐式转换为0和1.(当然,在您的情况下会返回0,因为&的优先级低于== 。)

  

你能用宏做吗?定义

我不明白这个问题。某些表达式在#if中的预处理时间内进行了评估,但是保持不变。

答案 1 :(得分:1)

这是C ++ Standard 5.19:

  

在一些地方,C ++需要表达式来计算整数或枚举常量:作为数组   bounds(8.3.4,5.3.4),作为case表达式(6.4.2),作为位字段长度(9.6),作为枚举器初始化器(7.2),   as static member initializers(9.4.2),以及整数或枚举非类型模板参数(14.3)。

constant-expression:  
            conditional-expression  
     

整数常量表达式只能包含文字(2.13),枚举数,常量变量或静态   使用常量表达式(8.5)初始化的整数或枚举类型的数据成员,非类型模板   整数或枚举类型的参数,以及sizeof表达式。浮动文字(2.13.3)可以   仅当它们被强制转换为整数或枚举类型时才会出现。仅键入转换为整数或枚举   类型可以使用。特别是,除了sizeof表达式外,不得使用函数,类对象,指针或引用。

     

其他表达式仅被视为常量表达式,仅用于非本地静态对象   初始化(3.6.2)。

答案 2 :(得分:1)

回答最后一点:你可以在模板中使用很多常量,但不能在宏中使用。

例如,sizeof(int)是一个常量表达式。但是sizeof表达式不会在宏上下文中进行评估。你不能写#if sizeof(int)==4

此外,预处理器根本无法处理浮点数学。

答案 3 :(得分:1)

我觉得你有点误解了。

常量表达式的实际评估由编译器完成,而不是预处理器。预处理器只评估宏,这是关于文本替换的。

如果你查看Boost.Preprocessor,你就会发现,如果你想让预处理器对它们进行评估,即使是简单的操作,如加法或索引,也无法用普通表达式表达。

BOOST_PP_ADD(4, 3) // expands to 7
BOOST_PP_SUB(4, 3) // expands to 1

这是在幕后通过变量手段完成的,例如你可以定义它(虽然它会非常无聊),如下所示:

#define ADD_IMPL_4_3 7

#define BOOST_PP_ADD(lhs, rhs) ADD_IMPL_##lhs##_##rhs

所以这与编译器的做法不同;)

至于测试您的编译器是否能够评估表达式,只需使用模板。

template <int x> struct f {};

typedef f< 3*4 / 5 > super_f_type;

如果它编译,那么编译器能够正确地评估表达式......因为否则它将无法实例化模板!

注意: BOOST_PP_ADD的实际定义要复杂得多,这是一个玩具示例,这可能无法正常运行&gt; BOOST_PP_ADD(BOOST_PP_SUB(4,3),3)

答案 4 :(得分:0)

它对我来说看起来不太标准,我确信C ++与bool类型一起使用,因此必须返回bool类型(因为你的代码是C ++,而不是C,因为模板)。可能会发生一些自动转换。作为一般经验法则,尽量避免使用C ++中的宏。