C++ 测试类型是否为(智能)指针的通用方法
在我的代码中,我需要测试给定给模板的类型是否是指针——不管它是否智能。根据boost的说法,没有可靠且通用的方法可以做到这一点(请参阅)——或者说有吗 到目前为止,我检查了以下内容:C++ 测试类型是否为(智能)指针的通用方法,c++,templates,shared-ptr,C++,Templates,Shared Ptr,在我的代码中,我需要测试给定给模板的类型是否是指针——不管它是否智能。根据boost的说法,没有可靠且通用的方法可以做到这一点(请参阅)——或者说有吗 到目前为止,我检查了以下内容: 答:T能否转换为void* B:TT有get()方法吗 C:T是否有一种称为element\u type的类型 D:get()是否返回元素类型* 如果(A | | B&&C&&D),那么我的类型必须是某种指针 以下是模板: template <typename T> class is_pointer
- 答:
能否转换为T
void*
- B:T
有T
get()方法吗
- C:
是否有一种称为T
的类型element\u type
- D:get()是否返回
元素类型*
template <typename T>
class is_pointer_type
{
typedef struct { char array[1]; } yes;
typedef struct { char array[2]; } no;
template <typename C> static yes test_g(decltype(&C::get));
template <typename C> static no test_g(...);
template <typename C> static yes test_e(typename C::element_type*);
template <typename C> static no test_e(...);
enum {
has_get = sizeof(test_g<T>(0)) == sizeof(yes),
has_element_type = sizeof(test_e<T>(0)) == sizeof(yes)
};
template <typename Q, bool OK = false>
struct get { struct type {}; };
template <typename Q>
struct get<Q, true>
{
typedef decltype(((Q*)nullptr)->get()) type;
};
template <typename Q, bool OK = false>
struct ptr { struct type {}; };
template <typename Q>
struct ptr<Q, true>
{
typedef typename Q::element_type* type;
};
public:
enum {
types_ok = std::is_same<
typename get<T, has_get>::type,
typename ptr<T, has_element_type>::type
>::value,
value = std::is_convertible<T, void*>::value || types_ok
};
};
模板
类是指针类型
{
typedef结构{char数组[1];}是;
typedef结构{char数组[2];}否;
模板静态yes测试(decltype(&C::get));
模板静态无测试(…);
模板静态是测试(类型名C::元素类型*);
模板静态无测试(…);
枚举{
has_get=sizeof(test_g(0))==sizeof(yes),
has_element_type=sizeof(test_e(0))==sizeof(yes)
};
模板
结构获取{struct type{};};
模板
结构获取
{
typedef decltype(((Q*)nullptr)->get())类型;
};
模板
结构ptr{struct type{};};
模板
结构ptr
{
typedef typename Q::element_type*type;
};
公众:
枚举{
类型\u ok=std::是否相同<
typename get::type,
typename ptr::type
>::价值,
值=标准::是否可转换::值| |类型|正常
};
};
到目前为止,似乎一切顺利。但这种推理有什么问题吗?我应该为不愉快的惊喜做好准备吗?那么const
/volatile
呢
更新(动机):
在你问我的动机的评论中,他们是对的,我欠你一个。用例是一个Lua -C++绑定库:当用“代码>模板推值(t值)< />代码将类实例暴露到Lua时,需要在代码< Ty= u const/Valtual/*/& 和<代码> t=某个指针< /COD>的任何组合中推断出基础类型<代码>代码>代码>。我需要知道底层类
U
是否已经在活页夹中注册。通过使用boost或定义自定义模板(如
template <typename C> static no test_pointer(C);
template <typename C> static yes test_pointer(C*);
模板静态无测试指针(C);
模板静态是测试_指针(C*);
但如果你更喜欢,你可以坚持使用void*解决方案
要检查智能指针,我建议改为检查适当的运算符。我认为,只有同时定义了运算符*和运算符->时,类型才可以被视为智能指针。所以你应该检查一下
template <typename C> static yes test_deref(decltype(&C::operator*));
template <typename C> static no test_deref(...);
template <typename C> static yes test_arrow(decltype(&C::operator->));
template <typename C> static no test_arrow(...);
template static yes test\u deref(decltype(&C::operator*);
模板静态无测试定义(…);
模板静态是测试箭头(decltype(&C::operator->);
模板静态无测试箭头(…);
并要求两个结果均为“是”。因此,最终的公式可以计算为“普通指针| |(has运算符*&&has运算符->)”
然而,它只是针对智能指针的解决方案。如果您还想将智能指针以外的类型(其他包装器、集合等)传递给Lua,那么情况就完全不同了,我不敢为此提出解决方案。您正在做boost说无法完成的事情。我已经准备好迎接惊喜了……这不是一个通用的解决方案,它是一个针对特定概念符号的解决方案。如果您遇到一个智能指针,它没有
元素\u类型
,而是有ptr\u类型
,或者需要使用特征,该怎么办?有些东西可以转换为void*
,但不是智能指针。特别是:早期对安全bool习惯用法的尝试,包括std::ios
。您认为为什么需要这个?我认为解决这个“问题”的办法毫无价值。然而,你认为这个问题的解决方案可以像这样解决,但没有告诉我们,是有用的。除非你为图书馆这样做,将模板声明为类似于
的指针,然后专门针对您实际使用的普通指针和智能指针类型,怎么样?std::unique\u ptr
是一种成熟的智能指针,它不提供操作符->
,而是提供操作符[]
。我明白您的观点,您的观点是正确的。然而,这正是unique_ptr应该被视为智能数组而不是智能指针的原因,尽管unique_ptr的名称不同。如果将这些指针传递给Lua,则必须直接为这些异常添加另一个测试,这是一个缺点。我们能想到类似的例外情况吗?同意。另外,C++11不再需要使用element\u type
,因为它应该与decltype(&C::operator*))相同。
如果其他人试图使用visual studio 2013执行此操作,它有时无法正常工作。我在2015年进行了测试,它确实在那里工作,所以我认为这只是一个编译器错误。我可以通过使用decltype(std::declval().operator*())*
和decltype(std::declval().operator->())
来解决这个问题,而不是使用decltype(&C::operator*)
和decltype(&C::operator->)
。