如何将模板类限制为仅具有类型别名的特定专业

时间:2017-03-02 13:11:48

标签: c++ templates c++14 anonymous-class

我的目标是拥有一个带有各种别名的模板化Wrapper类。这是一个简化的预览:

template < typename Type >
class Wrapper {
public:
   Wrapper(Type* resource) : ptr(resource) {}
   ~Wrapper() { free(ptr); }

private:
   Type* ptr;
}

void free(SDL_Window* ptr) { SDL_DestroyWindow(ptr); }
void free(SDL_Renderer* ptr) { SDL_DestroyRenderer(ptr); }

using Window = Wrapper<SDL_Window>;
using Renderer = Wrapper<SDL_Renderer>;

我想只允许创建Wrapper类的这些别名实例。其中一个原因是,它是SDL资源指针的包装器,它具有不同的内存释放功能,具体取决于指针的类型。

我想要实现的最佳方案是在我创建的别名的使用之外使Wrapper类不可见。也许有一个使用匿名命名空间的解决方案,但解冻意味着包装类不能在头文件中。

4 个答案:

答案 0 :(得分:2)

  

我希望实现的最佳方案是在使用我创建的别名之外使Wrapper类不可见。

使用private和包装类

可以实现
class WrapperAccessor {
    template < typename Type >
    class Wrapper {
    public:
       Wrapper(Type* resource) : ptr(resource) {}
       ~Wrapper() { free(ptr); }

    private:
       Type* ptr;
    };

public:
    using Window = Wrapper<SDL_Window>;
    using Renderer = Wrapper<SDL_Renderer>;
};

using Window = WrapperAccessor::Window;
using Renderer = WrapperAccessor::Renderer;

答案 1 :(得分:1)

std::enable_if怎么样,只为你的类/函数启用某些类型?

在C ++ 11和14中查看type_traits。您可以执行各种静态检查(在编译时检查)。例如,要检查类型是否符合您的预期,您可以使用:

std::is_same<T,int>::value

如果Tint,这将在编译时返回true

答案 2 :(得分:0)

我认为这可以提供帮助

template <typename T, bool Allowed>
class WrapperBase;


template <typename T>
class WrapperBase<T, true>
{
};

template <typename T>
class WrapperBase<T, false>;

template < typename Type >
class WrapperBaseHelper : public WrapperBase<T, boost::is_base_of<SDL_Window, T>::value | boost::is_base_of<SDL_Renderer>::value ...e.t.c >
{
...
};

答案 3 :(得分:0)

在您的具体情况下,我会使用std::unique_ptr,例如:

template <typename T, T value> struct Call; // c++17 should allow Call<auto F>

template <typename T, void (*f)(T*)>
struct Call<void (*)(T*), f>
{
    void operator ()(T* p) const { f(p); }
};

#define AUTO(F) decltype(F), F // not needed in C++17

using Window = std::unique_ptr<SDL_Window, Call<AUTO(&SDL_DestroyWindow)>>;
using Renderer = std::unique_ptr<SDL_Renderer, Call<AUTO(&SDL_DestroyRenderer)>>;

处理已删除的副本并纠正与您的代码段相反的移动语义。