2

我想通过使用constexpr函数而不是多constexpr if分支来简化代码。

这是带有旧代码注释的代码,旧代码使用msvc(vs 2017 with c++17) 和clang( android ndk r20) 编译,但使用clang 8in for windows x64in编译失败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 在编译时都是已知的

4

1 回答 1

4

运行时 Clang 会出现此错误:

note: cast that performs the conversions of a reinterpret_cast is not allowed in a constant expression
        return (intptr_t)value < 0;

将指针转换为整数类型不是常量表达式(因为它是 a reinterpret_cast),所以你不能使用if constexpr.

于 2019-08-22T13:57:32.350 回答