2014-10-17 2 views
1

У меня есть быстрый вопрос относительно печати оцененных значений #defines с использованием сообщения #pragma. Я использую MSVC++ в Visual Studio 2008.Печать полностью оцененного результата #define во время компиляции с использованием #pragma message()

Ниже приведен упрощенный пример:

#define __STR2__(x) #x 
#define __STR1__(x) __STR2__(x) 

#define WIDTH  10 
#define HEIGHT 10 
#define AREA  (WIDTH * HEIGHT) 

#pragma message("Area is: " __STR1__(AREA)) 

Теперь, когда я скомпилировать я получаю следующий результат:

>Area is: (10 * 10) 

Это не совсем то, что я хотеть. Есть ли способ распечатать оценку выражения #define, чтобы получить:

>Area is: 100 

во время компиляции. Возможно, это невозможно. В конце концов, я хочу, чтобы иметь возможность вызвать ошибку компилятора, если оцениваемое значение слишком велико. т.е.

#if(AREA > 1000) 
#pragma message(__ERROR__) 
#endif 

Некоторые из моих #defines использовать sizeof(), которые я считаю, вызывает проблемы в себе при оценке условных - но это проблема для будущего!

Я рассмотрел следующее сообщение How do I show the value of a #define at compile time in gcc, которое отлично до тех пор, пока значение #define определено как значение, а не объединение других #defines.

ответ

1

Препроцессор не будет выполнять математику для вас, он может только заменять маркеры и расширять макросы текстовым способом.

Если вы хотите, чтобы вычислить это значение во время компиляции вы должны пойти на constexpr (http://en.cppreference.com/w/cpp/language/constexpr, точнее это намекают компилятор вычислить его на этапе компиляции)

#include <iostream> 

#define WIDTH  10 
#define HEIGHT 10 

template<int a, int b> 
constexpr int getArea() { 
    static_assert(a*b < 1000, "Area is too big"); 
    return a*b; 
} 

const int area = getArea<WIDTH, HEIGHT>(); 

int main(void) { 
    std::cout << area; 
} 

Example

static_assert выполнит проверку области, если она слишком велика.

+0

Спасибо Marco. Я считаю, что этот подход будет работать с точки зрения оценки того, является ли область слишком большой - даже если макросы содержат операторы sizeof(), однако я не думаю, что это позволит мне распечатать значение «Area» во время компиляции ? Или, может быть, я что-то упустил. Как вы говорите, препроцессор может выводить только строки. – user3581793

+0

@ user3581793 Это будет печатать во время компиляции, если условие не выполняется. Вы имеете в виду печать во время компиляции и пусть компиляция продолжается? Это другая проблема, и для этого есть некоторые «хаки»: http://blogs.msdn.com/b/vcblog/archive/2007/05/17/diagnosing-hidden-odr-violations-in-visual- c-and-fixing-lnk2022.aspx. Я бы не рекомендовал их. –

+0

Да, я так думаю.По сути, я хотел бы распечатать значение «Area», независимо от того, что он был слишком большим. Поэтому, если значение меньше 1000, оно будет распечатываться, например, 'Area is 900', и компиляция будет продолжена. Assert прекратил компиляцию, если область была слишком большой. Также похоже, что static_assert() 'является частью только нового стандарта C++ 11, который я не могу использовать для этого проекта. – user3581793

0

Прекомпилятор может делать ограниченную математику в #if инструкциях. Это может быть достаточно для ваших нужд:

#define WIDTH  10 
#define HEIGHT 10 
#define AREA  (WIDTH * HEIGHT) 
#if AREA > 1000 
#error Oh bad, oh bad, oh bad 
#endif 

Для более сложной математики я второй, что Marco A. сказал, но вам не нужно, что в шаблоне или что-нибудь. Вы можете просто положить его со всеми вашими #define с, например:

#define WIDTH  10 
#define HEIGHT 10 
#define AREA  (WIDTH * HEIGHT) 
#define __ERROR__ "Oh bad, oh bad, oh bad" 
static_assert(AREA < 1000, __ERROR__); 

Или еще проще: static_assert(WIDTH * HEIGHT < 1000, "Oh bad, oh bad, oh bad");

Смежные вопросы