matt
matt

Reputation: 4244

what's the deal with compile time evaluation of constant arithmetic, and can it be done in the pre processor?

template <int T>
void aFunc(){}

int main()
{

    int anArray[45-32];

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

so this all compiles in VC++ 2005

is this standard? if so, what do the conditional operators return? 0 and 1? are there limits?

and the thing that interests me the most, can you do it in macros? defines?

Edit:

to elaborate further on the preprocessor bit:

#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" :(

Upvotes: 3

Views: 1138

Answers (5)

Matthieu M.
Matthieu M.

Reputation: 299950

I think you misunderstand a bit.

The actual evaluation of constant expressions is done by the compiler, not the preprocessor. The preprocessor only evaluates macros, which is about textual substitution.

If you check out Boost.Preprocessor, you'll realize that even simple operations like addition or soustractions cannot be expressed using common expressions if you want them to be evaluated by the preprocessor.

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

This is done, behind the scenes, by substitions means, for example you could define it (though it would be very tiresome) like so:

#define ADD_IMPL_4_3 7

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

So this is way different from what the compiler does ;)

As for testing whether or not your compiler is able to evaluate an expression or not, just use a template.

template <int x> struct f {};

typedef f< 3*4 / 5 > super_f_type;

If it compiles, then the compiler was able to properly evaluate the expression... since otherwise it would not have been able to instantiate the template!

Note: the actual definition of BOOST_PP_ADD is much more complicated, this is a toy example and this may not work properly > BOOST_PP_ADD(BOOST_PP_SUB(4,3),3).

Upvotes: 1

MSalters
MSalters

Reputation: 179927

To answer the last bit: there are many constants that you can use in templates, but not in macro's.

For instance, sizeof(int) is a constant expression. But sizeof expressions aren't evaluated in macro context. You can't write #if sizeof(int)==4.

Also, the preprocessor can't deal with floating-point math at all.

Upvotes: 1

Kirill V. Lyadvinsky
Kirill V. Lyadvinsky

Reputation: 99605

This is C++ Standard 5.19:

In several places, C + + requires expressions that evaluate to an integral or enumeration constant: as array bounds (8.3.4, 5.3.4), as case expressions (6.4.2), as bit-field lengths (9.6), as enumerator initializers (7.2), as static member initializers (9.4.2), and as integral or enumeration non-type template arguments (14.3).

constant-expression:  
            conditional-expression  

An integral constant-expression can involve only literals (2.13), enumerators, const variables or static data members of integral or enumeration types initialized with constant expressions (8.5), non-type template parameters of integral or enumeration types, and sizeof expressions. Floating literals (2.13.3) can appear only if they are cast to integral or enumeration types. Only type conversions to integral or enumeration types can be used. In particular, except in sizeof expressions, functions, class objects, pointers, or references shall not be used.

Other expressions are considered constant-expressions only for the purpose of non-local static object initialization (3.6.2).

Upvotes: 1

Gabriel Ščerb&#225;k
Gabriel Ščerb&#225;k

Reputation: 18570

It doesn't look very standard to me, what I am sure of is that C++ works with bool type, so bool type has to be returned (because you code is in C++, not C, because of templates). It might be that some automatic conversion happens. As a general rule of thumb, try to avoid macros in C++.

Upvotes: 0

kennytm
kennytm

Reputation: 523394

is this standard?

Yes. These are called "constant expressions". (Also see 5.19 [expr.const] in the C++ standard.)

if so, what do the conditional operators return? 0 and 1? are there limits?

false and true, which can be implicitly converted to 0 and 1. (Of course, in your case 0 is returned because & has lower precedence than ==.)

can you do it in macros? defines?

I don't understand this question. Some expressions are evaluated in preprocessing time in #if, but otherwise left untouched.

Upvotes: 7

Related Questions