【问题标题】:Recursively replace type by other type in a templated type用模板化类型中的其他类型递归替换类型
【发布时间】:2020-10-01 11:22:28
【问题描述】:

我正在寻找一种递归替换模板中的类型的方法。更具体地说,将T[N] 变成std::array<T, N>。如果包含非类型模板参数,问题是递归执行此操作。

目前,我有以下代码:

template<typename T>
struct replaced {
    using type = T;
};

template<typename T, std::size_t N>
struct replaced<T[N]> {
    using type = std::array<typename replaced<T>::type, N>;
};

template<template<typename...> typename T, typename... Ts>
struct replaced<T<Ts...>> {
    using type = T<typename replaced<Ts>::type...>;
};

没有非类型模板参数的测试用例可以正常工作,但是一旦引入了非类型模板参数,它就不再起作用了:

// this works (simple replacement)
static_assert(std::is_same_v<replaced<int[3]>::type, std::array<int, 3>>);

// this also works (nested types)
static_assert(std::is_same_v<
    replaced<std::tuple<int[2], std::pair<int, float[3]>>>::type,
    std::tuple<std::array<int, 2>, std::pair<int, std::array<float, 3>>>>);

// this doesn't work (non-type template parameters)
static_assert(std::is_same_v<
    replaced<std::array<int[2], 2>>::type,
    std::array<std::array<int, 2>, 2>>);

// instead this works, but shouldn't
static_assert(std::is_same_v<
    replaced<std::array<int[2], 2>>::type,
    std::array<int[2], 2>>);

Link to compiler explorer

我了解可变参数模板模板参数不适用于非类型模板参数。有什么方法可以修改replaced 的定义来实现我的目标?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    首先,好主意!

    尽管很糟糕,但从 C++20 开始,无法处理类型和非类型元素的泛型、可变参数组合。您只需要像std::array 一样开始处理极端情况。

    这似乎解决了那个特定问题,但当然它只对遵循与std::array相同模式的类有帮助

    template <template<typename, auto> class TC, typename T, auto N>
    struct replaced<TC<T, N>> {
        using type = TC<typename replaced<T>::type, N>;
    };
    

    https://godbolt.org/z/3j13W3

    【讨论】:

    • 很好的修复。我会添加template&lt;class... Ts&gt; using replaced_t = typename replaced&lt;Ts...&gt;::type; 以使使用也更加友好。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多