gpt4 book ai didi

c++ - 从函数的可变参数构建特定的元组

转载 作者:行者123 更新时间:2023-12-02 03:09:18 25 4
gpt4 key购买 nike

我喜欢使用std::tuple构建一个“ map ”,键是std::string,值是任何类型,定义如下:

template<typename... Args>
using Map = std::tuple<std::pair<std::string, Args>...>;

我有一个函数 MakeMap,它接受可变参数,将参数转换为 Map 并返回它:

template<typename... Args>
Map<???> MakeMap(Args&&... args) {
???
}

我希望 MakeMap 的参数采用 std::string, type1, std::string, type2, ... 格式(一个键后跟一个值),例如:

auto map = MakeMap("key1", 42, "key2", "hello world"); // OK
auto map = MakeMap(1, 2); // expects compiling error
auto map = MakeMap("key1", 42, "key2"); // expects compiling error

那么,如何实现函数MakeMap(在C++11中),以使上述调用语法起作用?

谢谢。

<小时/>

编辑

终于在@Kostas的大力帮助下我找到了答案,谢谢!

  1. 首先对参数进行配对:
template<typename... Args>
struct MapType;

template<>
struct MapType<> {
using type = typename std::tuple<>;
};

template<typename K, typename V, typename... Args>
struct MapType<K, V, Args...> {
using type = std::tuple<std::pair<std::string, V>, typename MapType<Args...>::type>;
};
  • 现在我们得到了一个嵌套的 std::tuple,我们需要将其展平(以下代码片段受到 this answer 的启发,感谢原作者):
  • template<typename T, typename U>
    struct FlattenHelper;

    template<typename... Args, typename... Heads, typename... Tails>
    struct FlattenHelper<std::tuple<Args...>, std::tuple<std::tuple<Heads...>, Tails...>> {
    using type = typename FlattenHelper<std::tuple<Args...>, std::tuple<Heads..., Tails...>>::type;
    };

    template<typename... Args, typename Head, typename... Tails>
    struct FlattenHelper<std::tuple<Args...>, std::tuple<Head, Tails...>> {
    using type = typename FlattenHelper<std::tuple<Args..., Head>, std::tuple<Tails...>>::type;
    };

    template<typename... Args>
    struct FlattenHelper<std::tuple<Args...>, std::tuple<>> {
    using type = std::tuple<Args...>;
    };

    template<typename T>
    struct Flatten;

    template<typename... Args>
    struct Flatten<std::tuple<Args...>> {
    using type = typename FlattenHelper<std::tuple<>, std::tuple<Args...>>::type;
    };
  • 现在我们可以像这样定义MakeMap:
  • template<typename... Args>
    using ReturnType = typename Flatten<typename MapType<Args...>::type>::type;

    template<typename K, typename V, typename... Args>
    ReturnType<K, V, Args...> MakeMap(K&& k, V&& v, Args&&... args) {
    // `std::forward` is omitted here
    return std::tuple_cat(std::make_tuple(std::make_pair(k, v)), MakeMap(args...));
    }

    std::tuple<> MakeMap() {
    return std::tuple<>();
    }

    最佳答案

    像往常一样 std::index_sequence 来救援(C++14,但可以在 C++11 中实现):

    // C++14 alias
    template <typename T>
    using decay_t = typename std::decay<T>::type;

    template <std::size_t I, typename T>
    using tuple_element_t = typename std::tuple_element<I, T>::type;

    template <std::size_t...Is, typename Tuple>
    Map<decay_t<tuple_element_t<2 * Is + 1, Tuple>>...>
    MakeMapImpl(std::index_sequence<Is...>, Tuple&& t)
    {
    return std::make_tuple(std::make_pair(std::get<2 * Is>(t),
    std::get<2 * Is + 1>(t))...);
    }

    template <typename... Args>
    auto MakeMap(Args&&... args)
    -> decltype(MakeMapImpl(std::make_index_sequence<sizeof...(Args) / 2>(), std::make_tuple(args...)))
    {
    static_assert(sizeof...(Args) % 2 == 0, "!");

    return MakeMapImpl(std::make_index_sequence<sizeof...(Args) / 2>(), std::make_tuple(args...));
    }

    Demo

    关于c++ - 从函数的可变参数构建特定的元组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58533468/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com