10

在我的代码中,我需要测试给模板的类型是否是指针——它是否智能。根据 boost 的说法,没有可靠和通用的方法来做到这一点(见这里)——或者有吗?

到目前为止,我检查了以下内容:

  • - 答:可以T转换为void*
  • B:Tget()方法吗?
  • C:T有一个类型叫element_type?
  • D:是否get()返回一个element_type*

如果 (A || B && C && D),那么我的结论是我的类型必须是某种指针。

这是模板:

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
    };
};

到目前为止,它似乎工作正常。但是这个推理有问题吗?我应该为不愉快的意外做好准备吗?const/呢volatile

更新(动机):

在评论中你问我的动机,他们是对的,我欠你一个。用例是一个 Lua - C++ 绑定库:当使用 向 Lua 公开一个类实例时,我需要以和的任意组合template <typename T> push_value(T value)推断底层类型。我需要知道底层类是否已经在活页夹中注册。UT = U const/volatile/*/&T = some_pointer<U>U

4

1 回答 1

1

很容易检查一个类型是否是一个指针,无论是使用 boost 还是定义一个具有专门化的自定义模板,如

template <typename C> static no test_pointer(C);
template <typename C> static yes test_pointer(C*);

但是,如果您更喜欢 void* 解决方案,您可以坚持使用它。

要检查智能指针,我建议改为检查适当的运算符。我认为只有同时定义了 operator* 和 operator-> 的类型才能被视为智能指针。所以你应该检查

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(...);

并要求两个结果都是“是”。因此,最终公式可以计算为“普通指针||(有运算符* && 有运算符->)”。

但是,它只是智能指针的解决方案。如果您还想将智能指针(其他包装器、集合等)以外的类型传递给 Lua,那就完全不同了,我不敢为此提出解决方案。

于 2012-05-19T19:03:20.543 回答