[英]Using constexpr to replace #define and #ifdef for conditional compilation
I am trying to replace the preprocessor #define and #if/#ifdef's that I am using to control conditional compilation with constexpr variables and ifs.我试图用 constexpr 变量和 ifs 替换我用来控制条件编译的预处理器 #define 和 #if/#ifdef。
Is it possible to declare constexpr variables such that they reproduce the #defines in that they don't allocate runtime storage, and that taking the address of one leads to a compile time error?是否可以声明 constexpr 变量,以便它们重现 #defines,因为它们不分配运行时存储空间,并且采用 1 的地址会导致编译时错误?
So in the headers I want to have something like所以在标题中我想有类似的东西
namespace ExampleNamespace
{
enum class Platform : int {Darwin, Linux, Windows};
constexpr Platform BuildPlatform = Platform::Darwin; // Line A.
};
While in the code I want在我想要的代码中
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.
Then aim is then to change the definition of BuildPlatform on Line A, such that Line B is evaluated at compile time (and the else clause gets discarded/not compiled) and lines C and D (and anything that does the same thing, or relies on runtime storage for BuildPlatform) generates a compiler error.然后目标是更改 A 行上 BuildPlatform 的定义,以便在编译时评估 B 行(并且 else 子句被丢弃/未编译)和 C 行和 D 行(以及执行相同操作或依赖的任何内容)在 BuildPlatform 的运行时存储上)生成编译器错误。
Is such a construct possible in C++17?在 C++17 中可以使用这样的构造吗?
It is partially possible:部分可能:
if constexpr (Platform::Darwin == BuildPlatform) { // Line B.
std::cout << "Platform is Darwin" << std::endl;
} else {
std::cout << "Platform is not Darwin" << std::endl;
}
but as template <typename T> void foo() {static_assert(false);}
is ill formed, code of all branches should have some kind of validity.但是由于
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
}
}
Maybe you can use this.也许你可以使用这个。
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)
{
}
For flags and integers, enum values work.对于标志和整数,枚举值有效。
For floating point values, there is no constexpr way that guarantees no ODR usage.对于浮点值,没有 constexpr 方法可以保证不使用 ODR。 ODR usage tends to cause storage to be created for the constant.
ODR 的使用往往会导致为常量创建存储。
You could use a constexpr function that returns a floating point value, but the function could easily take storage.您可以使用返回浮点值的 constexpr 函数,但该函数很容易占用存储空间。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.