简体   繁体   中英

Rewriting a parameter pack by replacing types

Here, I want to rewrite a variadic template parameter pack and replace occurrence of some type with another. Here is a pseudocode-like example:

#include <string>

template <typename Params,  typename Args>
struct TermRewrite {

    template <typename... Body>
    static auto constexpr eval(){
        // Fill here...
    }
};

int main() {
    TermRewrite<int, char>::eval<int, std::string, double>(); 
    // should give me pack of types as <char, std::string, double>
    // ie. it should replace type int with char in Body...

}

So that I can chain these term rewrites in the end. Basically, I want to transform the variadic template before forwarding it. How can I achieve this? I am not able to come-up with a solution. For all you want to know, this is a made-up exercise for myself. Also, do you have any suggestions on usability so that it is easier to chain TermRewrite calls?

You use parameter pack expansion with a metafunction taking a single argument

template<typename From, typename To>
struct replace
{
    template<typename T>
    using replace_fn = std::conditional_t<std::is_same_v<From, T>, To, T>;

    template<typename... Args>
    using apply = std::tuple<replace_fn<Args>...>;
};

Note you have to save the result as a template taking parameter packs like std::tuple .

If you want to chain the replacement, you could write

template<typename From, typename To, typename... Args>
struct replace_impl
{
    template<typename T>
    using replace_fn = std::conditional_t<std::is_same_v<From, T>, To, T>;
    using type = std::tuple<replace_fn<Args>...>;
};

template<typename From, typename To, typename... Args>
struct replace_impl<From, To, std::tuple<Args...>>
{
    template<typename T>
    using replace_fn = std::conditional_t<std::is_same_v<From, T>, To, T>;
    using type = std::tuple<replace_fn<Args>...>;
};

template<typename From, typename To>
struct replace
{
    template<typename... Args>
    using apply = typename replace_impl<From, To, Args...>::type;
};

And use as

replace<char, float>::apply<replace<int, char>::apply<int, char, bool>>

But be careful that this means you are treating a single std::tuple not as a type, but a list of types.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM