我正在尝试替换预处理器 #define 和 #if/#ifdef,我用它来控制带有constexpr变量和ifs的条件编译。
是否可以声明 constexpr 变量,以便它们在不分配运行时存储的情况下重现 #defines,并且获取一个地址会导致编译时错误?
编辑以添加代码示例。
所以在标题中,我想有类似的东西
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.
然后目标是更改 A 行上 BuildPlatform 的定义,使得 B 行在编译时被计算(else 子句被丢弃/未编译(,而 C 行和 D(以及任何做同样事情的东西,或者依赖于 BuildPlatform 的运行时存储(都会生成编译器错误。
在 C++17 中这样的结构可能吗?
部分可能:
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
}
}
也许你可以使用它。
enum class Platform { Darwin, Linux, Windows };
#ifdef __darwin__
constexpr Platform BuildPlatform = Platform::Darwin;
#elif __linux__
constexpr Platform BuildPlatform = Platform::Linux;
#elif __WIN32
constexpr Platform BuildPlatform = Platform::Windows;
#endif
// your code then uses it like this
if constexpr (BuildPlatform == Platform::Darwin)
{
}
else if constexpr (BuildPlatform == Platform::Linux)
{
}
else if constexpr (BuildPlatform == Platform::Windows)
{
}
对于标志和整数,枚举值有效。
对于浮点值,没有保证不使用 ODR 的 constexpr 方法。 ODR 使用往往会导致为常量创建存储。
您可以使用返回浮点值的 constexpr 函数,但该函数很容易占用存储。