为什么这个 constexpr if 不编译
why this constexpr if doesn't compile
我想通过使用 constexpr
函数而不是多个 constexpr
if
分支来简化代码。
这是旧代码注释掉的代码
旧代码使用 msvc
(与 2017 使用 c++17
)和 clang
(android ndk r20
)编译,但无法使用 clang 8
编译 [=22] =] 在 visual studio
!
并且新代码既不使用 msvc
也不使用 clang
进行编译
template <class T>
constexpr bool IsValueNegative(T value) // this function should be evaluated at runtime but it it isn't !
{
if constexpr (std::is_integral_v<T>) // SOCKET = ULONG_PTR and linux handles are int
{
return value < 0;
}
else // HANDLE = void * and most other handles are pointers
{
return (intptr_t)value < 0;
}
}
template <class T, const T null_value, bool no_negative = true>
class HandleWrapper
{
public:
HandleWrapper() : handle(null_value)
{}
HandleWrapper(T h) : handle(h)
{
if constexpr (no_negative) // to convert INVALID_HANDLE_VALUE to nullptr
{
if constexpr (!IsValueNegative(null_value)) // SOCKET invalid handle is -1
{
if (IsValueNegative(handle)) //
handle = null_value;
}
/*
if constexpr (std::is_integral_v<T>)
{
if constexpr (null_value >= 0)
{
if (handle < 0)
handle = null_value;
}
}
else
{
if constexpr ((intptr_t)null_value >= 0) // clang 8 can't compile this , don't know why
{
if ((intptr_t)handle < 0)
handle = null_value;
}
}
*/
}
}
private:
T handle;
};
template <class T, const T null_value, bool no_negative, auto Deleter>
struct HandleHelper
{
using pointer = HandleWrapper<T, null_value, no_negative>;
void operator()(pointer p)
{
if constexpr (!no_negative)
{
if (!IsValueNegative(null_value) && IsValueNegative(T(p))) // pseudo handle from GetCurrentProcess or GetCurrentThread
return;
}
/*
if constexpr (!no_negative && )
{
if ((uintptr_t)T(p) <= 0)
{
std::cout << "[*] this is a pseudo handle\n";
return;
}
}
*/
Deleter(T(p));
}
};
using Handle = std::unique_ptr<HandleWrapper<HANDLE, nullptr, true>, HandleHelper<HANDLE, nullptr, true, CloseHandle>>;
using ProcessHandle = std::unique_ptr<HandleWrapper<HANDLE, nullptr, false>, HandleHelper<HANDLE, nullptr, false, CloseHandle>>;
using ThreadHandle = ProcessHandle;
新代码在这一行编译失败:
if constexpr (!IsValueNegative(null_value)) // SOCKET invalid handle is -1
msvc 的错误代码是:
Error C2131 expression did not evaluate to a constant
来自 clang 8 :
constexpr if condition is not a constant expression
然而所有 null_value 在编译时都是已知的
Clang 在您 运行 时给出此错误:
note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression
return (intptr_t)value < 0;
将指针转换为整数类型不是常量表达式(因为它是一个reinterpret_cast
),所以不能使用if constexpr
.
我想通过使用 constexpr
函数而不是多个 constexpr
if
分支来简化代码。
这是旧代码注释掉的代码
旧代码使用 msvc
(与 2017 使用 c++17
)和 clang
(android ndk r20
)编译,但无法使用 clang 8
编译 [=22] =] 在 visual studio
!
并且新代码既不使用 msvc
也不使用 clang
template <class T>
constexpr bool IsValueNegative(T value) // this function should be evaluated at runtime but it it isn't !
{
if constexpr (std::is_integral_v<T>) // SOCKET = ULONG_PTR and linux handles are int
{
return value < 0;
}
else // HANDLE = void * and most other handles are pointers
{
return (intptr_t)value < 0;
}
}
template <class T, const T null_value, bool no_negative = true>
class HandleWrapper
{
public:
HandleWrapper() : handle(null_value)
{}
HandleWrapper(T h) : handle(h)
{
if constexpr (no_negative) // to convert INVALID_HANDLE_VALUE to nullptr
{
if constexpr (!IsValueNegative(null_value)) // SOCKET invalid handle is -1
{
if (IsValueNegative(handle)) //
handle = null_value;
}
/*
if constexpr (std::is_integral_v<T>)
{
if constexpr (null_value >= 0)
{
if (handle < 0)
handle = null_value;
}
}
else
{
if constexpr ((intptr_t)null_value >= 0) // clang 8 can't compile this , don't know why
{
if ((intptr_t)handle < 0)
handle = null_value;
}
}
*/
}
}
private:
T handle;
};
template <class T, const T null_value, bool no_negative, auto Deleter>
struct HandleHelper
{
using pointer = HandleWrapper<T, null_value, no_negative>;
void operator()(pointer p)
{
if constexpr (!no_negative)
{
if (!IsValueNegative(null_value) && IsValueNegative(T(p))) // pseudo handle from GetCurrentProcess or GetCurrentThread
return;
}
/*
if constexpr (!no_negative && )
{
if ((uintptr_t)T(p) <= 0)
{
std::cout << "[*] this is a pseudo handle\n";
return;
}
}
*/
Deleter(T(p));
}
};
using Handle = std::unique_ptr<HandleWrapper<HANDLE, nullptr, true>, HandleHelper<HANDLE, nullptr, true, CloseHandle>>;
using ProcessHandle = std::unique_ptr<HandleWrapper<HANDLE, nullptr, false>, HandleHelper<HANDLE, nullptr, false, CloseHandle>>;
using ThreadHandle = ProcessHandle;
新代码在这一行编译失败:
if constexpr (!IsValueNegative(null_value)) // SOCKET invalid handle is -1
msvc 的错误代码是:
Error C2131 expression did not evaluate to a constant
来自 clang 8 :
constexpr if condition is not a constant expression
然而所有 null_value 在编译时都是已知的
Clang 在您 运行 时给出此错误:
note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression
return (intptr_t)value < 0;
将指针转换为整数类型不是常量表达式(因为它是一个reinterpret_cast
),所以不能使用if constexpr
.