我试图用constexpr变量和ifs替换用于控制条件编译的预处理器#define和#if /#ifdef。
是否可以声明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中这样的构造可能吗?
答案 0 :(得分:1)
部分可行:
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
}
}
答案 1 :(得分:0)
对于标志和整数,枚举值有效。
对于浮点值,没有任何constexpr方法可以保证不使用ODR。使用ODR往往会导致为该常数创建存储。
您可以使用constexpr函数来返回浮点值,但是该函数可以轻松地进行存储。
答案 2 :(得分:0)
也许您可以使用它。
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)
{
}