Есть ли область видимости у директив препроцессора C++?
Нет, директивы препроцессора не ограничены никакими областями видимости. Они заменяют абсолютно все вхождения соответствующего имени после своего определения. Пример:

namespace what {
#define apples 2
}

namespace stuff {
    class foo {
    private:
        int apples = 3;  // ОШИБКА: 2 - недопустимое имя
    public:
        int read_apples() {
            return apples;  // 2
        }
    };
}

Мораль: не используйте макросы там, где можно обойтись constexpr константами или inline функциями. А там, где они необходимы, давайте им длинные страшные КРИЧАЩИЕ_ИМЕНА.
Областей видимости у директив нет, но есть #undef
Почитайте про подход X-MACRO

Однако, нужно понимать, что в C++ применение препроцессора, как правило, это самое последнее средство, которое следует использовать.

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

И да, если вы намылились объявлять через препроцессор константы, тресните себе клавиатурой по рукам посильнее. Для объявления констант есть constexpr.