我想通过使用constexpr
函数而不是多constexpr
if
分支来简化代码。
这是带有旧代码注释的代码,旧代码使用msvc
(vs 2017 with c++17
) 和clang
( android ndk r20
) 编译,但使用clang 8
in for windows x64
in编译失败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
从铿锵声 8 :
constexpr if condition is not a constant expression
但是所有的 null_value 在编译时都是已知的