微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何使用模板查找参数T的最大可引用级别

如何解决如何使用模板查找参数T的最大可引用级别

我正在设计一个“ dereferencer” 类,很有趣。

我写了structalias

template <class _T>
using deref_type = decltype(*std::declval<_T>());

template <class _T,class _SFINAE>
struct is_derefable : std::false_type {};

template <class _T>
struct is_derefable< _T,deref_type<_T> > : std::true_type
{
    using return_type = deref_type<_T>;
};

template<class _T>
using check_derefable = is_derefable<T,deref_type<T>>;

假设有一个类型为T = std::vector<int**>::iterator的变量,它是被迭代到2级指针中的迭代器,因此具有3级可撤销性。

在这里,我想知道在编译时处任意类型T的最大“可引用性”。

std::cout << deref_level<std::vector<int**>::iterator>::max << std::endl; // this should prints 3

我认为这类似于在编译时生成序列:Template tuple - calling a function on each element ,但我无法对其进行具体描绘。

这是我尝试过的:

template<class _TF,class _T>
struct derefability {};

template<int _N,class _derefability>
struct deref_level;

template<int _N,class _T>
struct deref_level<_N,derefability<std::false_type,_T>>
{
    static const int max = _N;
};

template<int _N,derefability<std::true_type,_T>> : 
    deref_level<_N + 1,derefability<typename check_derefable<deref_type<_T>>::type,deref_type<_T>>>{};

deref_level<0,derefability<check_derefable<T>::type,T>::max;

但是它不起作用...(编译器说 max 不是tje类的成员)。出了什么问题?

解决方法

这是直接使用SFINAE的递归实现:

template <class T,class = void>
struct deref_level {
    enum : std::size_t { value = 0 };
};

template <class T>
struct deref_level<T,decltype(void(*std::declval<T const &>()))> {
    enum : std::size_t { value = deref_level<decltype(*std::declval<T const &>())>::value + 1 };
};

See it live on Wandbox

,

我不知道您的模板示例出了什么问题,但这是一个使用递归consteval函数的实现:

#include <type_traits>

template<typename T,int N = 0>
consteval int deref_level()
{
    if constexpr (std::is_pointer<T>::value) {
        typedef typename std::remove_pointer<T>::type U;
        return deref_level<U,N + 1>();
    } else {
        return N;
    }
}

int main() {
    return deref_level<int****>(); // Returns 4
}
,

经过几天的工作,我能够编写出能够在MSVC13中不会引起错误的代码。

首先,我需要一个功能强大的模块来检查该类型的 可解除引用性

由于结构级SFINAE检查失败,因此我根据答案:link采用了另一种方法,该方法使用auto->decltype表达式从重载函数推导返回类型。 / p>

template<class T>
struct is_dereferenceable
{
private:
    template<class _type>
    struct dereferenceable : std::true_type
    {
        using return_type = _type;
    };

    struct illegal_indirection : std::false_type
    {
        using return_type = void*;
    };

    template<class _type>
    static auto dereference(int)->dereferenceable<
        decltype(*std::declval<_type>())>;

    template<class>
    static auto dereference(bool)->illegal_indirection;

    using dereferenced_result = decltype(dereference<T>(0));

public:
    using return_type = typename dereferenced_result::return_type;
    static const bool value = dereferenced_result::value;
};

现在我有一个强大的可解除引用性检查器,其余部分变得很容易。

template< class T,class D = typename is_dereferenceable<T>::return_type >
struct dereferenceability;

template< class T >
struct dereferenceability<T,void*>
{
    using level = std::integral_constant<int,0>;
};

template< class T,class D >
struct dereferenceability<T,D&>
{
    using level = std::integral_constant<int,dereferenceability<D>::level::value + 1>;
};

int main()
{
    static_assert(dereferenceability<int>::level::value == 0,"something went wrong");
    static_assert(dereferenceability<int****>::iterator>::level::value == 4,"something went wrong");
    return 0;
}

我已经在Visual Studio 2013中测试了上面的代码,并且没有发生错误。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。