C++ 将变量模板限制为类型列表
我正试图通过添加智能指针使一些代码现代化。例如:C++ 将变量模板限制为类型列表,c++,templates,gstreamer,unique-ptr,C++,Templates,Gstreamer,Unique Ptr,我正试图通过添加智能指针使一些代码现代化。例如: GstElement *pipeline = gst_pipeline_new("test-pipeline"); gst_object_unref(pipeline); 可以重写: struct GstElementDeleter { void operator()(GstElement* p) { gst_object_unref(p); } }; std::unique_ptr<GstElement, GstElement
GstElement *pipeline = gst_pipeline_new("test-pipeline");
gst_object_unref(pipeline);
可以重写:
struct GstElementDeleter {
void operator()(GstElement* p) { gst_object_unref(p); }
};
std::unique_ptr<GstElement, GstElementDeleter> pipeline = gst_pipeline_new("test-pipeline");
template<typename T>
struct GPointerDeleter {
void operator()(T* p) { gst_object_unref(p); }
};
std::unique_ptr<GstElement, GPointerDeleter<GstElement>> pipeline = gst_pipeline_new("test-pipeline");
但我想做的是将其限制为仅处理可以使用
gst\u object\u unref
解除分配的类型。是否有一种方法可以声明模板仅与类型列表一起工作-GstElement
、GstBus
等?也许您可以将模板设置为操作符()
(因此无需显式定义智能指针的模板参数),并使用SFINAE启用操作符()
仅适用于允许的类型
struct GPointerDeleter
{
template <typename T>
typename std::enable_if<std::is_same<T, GstElement>::value
|| std::is_same<T, GstBus>::value
/* or other cases */
>::type operator() (T * p) const
{ gst_object_unref(p); }
};
也许是一种性格特征?看看你以前是否见过这些
template<typename T>
struct can_gst_unref : std::false_type { };
// for each type...
template<> struct can_gst_unref<GstElement> : std::true_type { };
// convenient alias, as is convention for type traits
template<typename T>
inline constexpr bool can_gst_unref_v = can_gst_unref<T>::value;
// now conditionally define operator() in your deleter
struct GstDeleter {
template<typename T>
std::enable_if_t<can_gst_unref_v<T>> operator()(T* p) { gst_object_unref(p); }
};
// Making the function a template instead of the class reduces clutter at usage
std::unique_ptr<GstElement, GstDeleter> works(gst_pipeline_new("test-pipeline"));
// can_gst_unref is not specialized to std::string
// so the general case takes over, and gives can_gst_unref_v<std::string> = false
// std::enable_if_t thus doesn't produce a type, and operator() is not defined, because it has no return type
// therefore, this doesn't compile
std::unique_ptr<std::string, GstDeleter> whoops;
模板
结构can\u gst\u unref:std::false\u type{};
//对于每种类型。。。
模板结构can\u gst\u unref:std::true\u type{};
//方便的别名,这是类型特征的惯例
模板
内联constexpr bool can\u gst\u unref\u v=can\u gst\u unref::value;
//现在,在删除程序中有条件地定义运算符()
结构GstDeleter{
模板
std::enable_if_t operator()(t*p){gst_object_unref(p);}
};
//使函数成为模板而不是类可以减少使用时的混乱
标准:独特的ptr工程(gst管道新(“测试管道”);
//can\U gst\U unref不是专用于std::string的
//因此,一般情况下,给出can\u gst\u unref\u v=false
//std::如果\u t因此不生成类型,则启用\u,并且未定义运算符(),因为它没有返回类型
//因此,这不会编译
性病:独特的呼;
您可以使用std::enable_,如果子集不应该只是GstObject*
,那么struct GPointerDeleter{void operator()(GstObject*p)const{gst\u object_unref(p);}
?@Jarod42您可能会认为,但是不-它们实际上没有定义为GstObject,它们的结构中有一个指向GstObject的指针。如果问题标记为C++17,则可以用std::enable\u和std::is_same\u v
@churill缩短。但问题只标注了C++。我们知道OP至少使用了C++11(使用std::unique\u ptr
),当然,我只使用与C++11兼容的代码。static\u assert
在这里似乎比SFINAE更合适。@Jarod42-你的意思是“没有其他选择,所以软错误会给出与硬错误相同的结果”吗?嗯。。。也许你是对的…@Jarod42-是的:是有意的;还可以简化智能指针声明。我试着解释,但也许我的英语错了。
template<typename T>
struct can_gst_unref : std::false_type { };
// for each type...
template<> struct can_gst_unref<GstElement> : std::true_type { };
// convenient alias, as is convention for type traits
template<typename T>
inline constexpr bool can_gst_unref_v = can_gst_unref<T>::value;
// now conditionally define operator() in your deleter
struct GstDeleter {
template<typename T>
std::enable_if_t<can_gst_unref_v<T>> operator()(T* p) { gst_object_unref(p); }
};
// Making the function a template instead of the class reduces clutter at usage
std::unique_ptr<GstElement, GstDeleter> works(gst_pipeline_new("test-pipeline"));
// can_gst_unref is not specialized to std::string
// so the general case takes over, and gives can_gst_unref_v<std::string> = false
// std::enable_if_t thus doesn't produce a type, and operator() is not defined, because it has no return type
// therefore, this doesn't compile
std::unique_ptr<std::string, GstDeleter> whoops;