Использование constexpr для замены #define и #ifdef для условной компиляции - PullRequest
0 голосов
/ 21 сентября 2018

Я пытаюсь заменить препроцессор #define и # if / # ifdef, которые я использую для управления условной компиляцией с переменными constexpr и ifs.

Можно ли объявить переменные constexpr так, чтобы они воспроизводили# определяет, что они не выделяют хранилище времени выполнения и что получение адреса одного приводит к ошибке времени компиляции?

Отредактировано для добавления примера кода.

Так что в заголовках я хочуиметь что-то вроде

namespace ExampleNamespace
{
  enum class Platform : int {Darwin, Linux, Windows};

  constexpr Platform BuildPlatform = Platform::Darwin;  // Line A.
};

В то время как в коде я хочу

if constexpr (Platform::Darwin == BuildPlatform)        // Line B.
  {
    cout << "Platform is Darwin" << endl;
  }
else
  {
    cout << "Platform is not Darwin" << endl;
  };

const Platform *const PlatformAddress = &BuildPlatform; // Line C.
const Platform &BuildPlatform2 = BuildPlatform;         // Line D.

Тогда цель состоит в том, чтобы затем изменить определение BuildPlatform в строке A, чтобы строка B вычислялась при компиляцииtime (и предложение else отбрасывается / не компилируется), а строки C и D (и все, что делает то же самое или полагается на хранилище времени выполнения для BuildPlatform) генерирует ошибку компилятора.

Возможна ли такая конструкцияв С ++ 17?

Ответы [ 2 ]

0 голосов
/ 21 сентября 2018

Для флагов и целых чисел значения enum работают.

Для значений с плавающей запятой не существует способа constexpr, который гарантирует отсутствие использования ODR.Использование ODR приводит к созданию хранилища для константы.

Вы можете использовать функцию constexpr, которая возвращает значение с плавающей запятой, но функция может легко занять память.

0 голосов
/ 21 сентября 2018

Это частично возможно:

if constexpr (Platform::Darwin == BuildPlatform) {        // Line B.
    std::cout << "Platform is Darwin" << std::endl;
} else {
    std::cout << "Platform is not Darwin" << std::endl;
}

, но, поскольку template <typename T> void foo() {static_assert(false);} плохо сформирован, код всех ветвей должен иметь некоторую валидность.

#ifdef (DarwinPlatform) // constexpr cannot be used here, you have to 
                        //rely on MACRO here
# include <darwin.h>     // Some OS specific header
#endif

void foo()
{
    if constexpr (Platform::Darwin == BuildPlatform) {
        DarwinMethod(); // Won't compile on other platforms as
                        // the method doesn't exist.
        // you should make the block template with template dependent code
        // to allow code to compile.
        // as http://coliru.stacked-crooked.com/a/c695575e4dcdecee
    }
}
...