是否可以将指针视为非类型模板参数中的整数类型?

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了是否可以将指针视为非类型模板参数中的整数类型?相关的知识,希望对你有一定的参考价值。

我正在尝试创建一个模板,其中默认值可以作为非类型参数传递。

原始类型(WINAPI的HANDLE)是从编译器角度来看的指针类型,但从用户角度来看则被视为整数类型。

// Somewhere in system headers
#define INVALID_HANDLE_VALUE ((HANDLE)(LONG_PTR)-1)
typedef void *HANDLE;

// My code
template<typename Handle, Handle Default>
class HandleWrapper
{
    ...
};

HandleWrapper<HANDLE, INVALID_HANDLE_VALUE>; // error: invalid nontype template argument of type `HANDLE`

我目前的解决方法:

template<typename Handle, uintptr_t Default>
class HandleWrapper
{
    static_assert(std::is_pointer<Handle>::value, "Handle must be a pointer");
    static constexpr Handle DefaultHandle = reinterpret_cast<Handle>(Invalid);
};

我想正确的解决方案是以某种方式指定typename Handle应该被视为一个整数类型(uintptr_t),只要会话没有缩小。

答案

在我的代码中,我有一个模板化的句柄包装类,我使用它,但我采用不同于你的方法。我为每个要包装的句柄类型定义了一个单独的traits类,然后使用template参数指定在包装器中使用哪些特征。

尝试在你的情况下做类似的事情,例如:

struct InvalidHandleTraits
{
    using HandleType = HANDLE;
    static constexpr HANDLE DefaultHandle = INVALID_HANDLE_VALUE;
    //...
    static void Close(HANDLE h) { CloseHandle(h); }
    //...
};

struct NullHandleTraits
{
    using HandleType = HANDLE;
    static constexpr HANDLE DefaultHandle = NULL;
    //...
    static void Close(HANDLE h) { CloseHandle(h); }
    //...
};

... other traits as needed...

template<typename traits = InvalidHandleTraits>
class HandleWrapper
{
public:
    using HandleType = typename traits::HandleType;

    HandleWrapper(HandleType h = traits::DefaultHandle) : m_handle(h) { std::cout << "constructor: " << h << std::endl; }
    ~HandleWrapper() { traits::Close(m_handle); }
    //...

    operator HandleType() { return m_handle; }

private:
    HandleType m_handle;
};

然后你可以在需要时使用所需的traits类,例如:

HandleWrapper<> h = CreateFile(...);
// or:
// HandleWrapper<InvalidHandleTraits> h = CreateFile(...);

HandleWrapper<NullHandleTraits> h = CreateFileMapping(...);

Live Demo

以上是关于是否可以将指针视为非类型模板参数中的整数类型?的主要内容,如果未能解决你的问题,请参考以下文章

非类型模板参数

推断指针非类型模板参数的类型

我可以将 C++17 无捕获 lambda constexpr 转换运算符的结果用作函数指针模板非类型参数吗?

Chapter16:模板

指向任意类方法的模板非类型指针

模板类中的非模板函数[关闭]