簡體   English   中英

如何為 c++17 中的通用嵌套容器編寫 function?

[英]How to write function for generic nested container in c++17?

我想實現一個 function ,其參數類型為List<List<int>>其中List可能是std::vectorstd::list ,甚至是帶有自定義分配器的std::vector ,同時,它也接受原始大括號括起來的表達式

目前我有一個本地嘗試如下

#include <iostream>
#include <list>
#include <vector>

template<typename LLO = std::vector<std::vector<int>>>
void f(const LLO& a) {
   for (const auto& i : a) {
      for (const auto& j : i) {
         std::cout << j;
      }
      std::cout << '\n';
   }
}

template<typename LO = std::vector<int>, int = 0>
void f(const std::initializer_list<LO>& a) {
   f(std::vector(a));
}

int main() {
   f({{1, 2}, {3, 4}});
   f({std::vector{1, 2}, {3, 4}});
   f(std::list{std::list{1, 2}, {3, 4}});
   f({std::list{1, 2}, {3, 4}});
}

最重要的測試是f({std::list{1, 2}, {3, 4}}) ,它要求我顯式地為 std::initializer_list 編寫一個丑陋的重載。

事實上,在我的情況下,我有三個像這樣的嵌套容器類型的 arguments,如果我使用這個解決方案,我必須編寫2^3=8重載函數

我想知道是否有一些好看的解決方案,我的代碼在c++17下,如果可以在c++20中用概念輕松實現,這次對我沒有幫助,但我還是很好奇。

如果您可以容忍使用輔助 function,您可以這樣做:

#include <iostream>
#include <list>
#include <vector>

template<class LLO>
LLO
make_param(LLO&& a) { return std::forward<LLO>(a); }

template<template<class...> class Cont = std::vector, class T = int, class... Rest>
auto
make_param(std::initializer_list<Cont<T, Rest...>> ilist)
{
    return Cont<Cont<T, Rest...>, Rest...>(ilist);
}


template<class LLO>
void f(const LLO& p)
{
    //code here
}

template<class LLO1, class LLO2>
void f(const LLO1& p1, const LLO2& p2)
{
    //more code here
}

int main()
{
    f(make_param({{1, 2}, {3, 4}}));
    f(make_param({std::vector{1, 2}, {3, 4}}));
    f(make_param(std::list{std::list{1, 2}, {3, 4}}));
    f(make_param({std::list{1, 2}, {3, 4}}));

    std::vector<int, std::allocator<float>> v;
    f(make_param({v, v}));

    f(make_param({{1, 2}, {3, 4}}), make_param({std::list{1, 2}, {3, 4}}));
}

不必為每個參數使用輔助 function 的另一種解決方案可能是這樣的:

#include <iostream>
#include <list>
#include <vector>
#include <tuple>

template<class Item, template<class...> class Tuple, class... Types, std::size_t... Is>
std::tuple<Types..., Item>
tuple_append_impl(Item&& item, Tuple<Types...>& t, std::index_sequence<Is...>)
{
    return { std::move(std::get<Is>(t))..., std::forward<Item>(item) };
}

template<class Item, class... Types>
std::tuple<Types..., Item>
tuple_append(Item&& item, std::tuple<Types...>& t)
{
    return tuple_append_impl(std::forward<Item>(item), t, std::make_index_sequence<sizeof...(Types)>());
}

template<class... Conts>
struct param
{
    template<class LLO>
    param<Conts..., LLO>
    operator()(LLO&& a)
    {
        return { tuple_append(std::forward<LLO>(a), conts) };
    }

    template<template<class...> class Cont = std::vector, class T = int, class... Rest>
    param<Conts..., Cont<Cont<T, Rest...>, Rest...>>
    operator()(std::initializer_list<Cont<T, Rest...>> ilist)
    {
        return { tuple_append(Cont<Cont<T, Rest...>, Rest...>(ilist), conts) };
    }

    std::tuple<Conts...> conts;
};

template<>
struct param<>
{
    template<class LLO>
    param<LLO>
    operator()(LLO&& a) { return {std::forward<LLO>(a)}; }

    template<template<class...> class Cont = std::vector, class T = int, class... Rest>
    param<Cont<Cont<T, Rest...>, Rest...>>
    operator()(std::initializer_list<Cont<T, Rest...>> ilist)
    {
        return {Cont<Cont<T, Rest...>, Rest...>(ilist)};
    }
};

param() -> param<>;

template<class Cont>
void f(const param<Cont>& p)
{
    //function taking one param
    auto& llo = std::get<0>(p.conts);
}

template<class Cont1, class Cont2>
void f(const param<Cont1, Cont2>& p)
{
    //function taking two param
    auto&& llo0 = std::get<0>(p.conts);
    auto&& llo1 = std::get<1>(p.conts);
}

template<class Cont1, class Cont2, class Cont3>
void f(const param<Cont1, Cont2, Cont3>& p)
{
    //function taking three param
}

template<class... Conts>
void f2(const param<Conts...>& p)
{
    //function taking arbitrary amount of params
}

int main()
{
    f(param<>()({{1, 2}, {3, 4}}));
    f(param<>()({std::vector{1, 2}, {3, 4}}));
    f(param<>()(std::list{std::list{1, 2}, {3, 4}}));
    f(param<>()({std::list{1, 2}, {3, 4}}));

    f(param<>()({{1, 2}, {3, 4}})
            ({std::list{1, 2}, {3, 4}})
            (std::list{std::list{1, 2}, {3, 4}}));
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM