Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/angular/27.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 递归iterable模板函数c++;_C++_Arrays_Recursion - Fatal编程技术网

C++ 递归iterable模板函数c++;

C++ 递归iterable模板函数c++;,c++,arrays,recursion,C++,Arrays,Recursion,我对如何将类型信息传递给循环链感到困惑 下面代码的目标是做一些类似python的“,”.join([“a”,“b”,“c”]),但是以递归方式,这样我就可以连接一个数组的数组。。。字符串,其中分隔符的数量与结构的深度相同 下面是我的一些注释(试图让它编译)代码: 以更干净的方式做这件事的方法的额外积分。 更多关于如何使用任意iterables(数组等)的奖励点这里是我将如何使用它的示意图: #include <iostream> #include <algorithm>

我对如何将类型信息传递给循环链感到困惑

下面代码的目标是做一些类似python的
“,”.join([“a”,“b”,“c”])
,但是以递归方式,这样我就可以连接一个数组的数组。。。字符串,其中分隔符的数量与结构的深度相同

下面是我的一些注释(试图让它编译)代码:

以更干净的方式做这件事的方法的额外积分。
更多关于如何使用任意iterables(数组等)的奖励点这里是我将如何使用它的示意图:

#include <iostream>
#include <algorithm>
#include <type_traits>
#include <sstream>
#include <vector>
#include <tuple>

// this allows us to test if a element should be recursed into

template <typename iterable, typename tag = void>
struct is_iterable
{
    static constexpr bool value = false;
};

template <typename iterable>
struct is_iterable <iterable, std::void_t <decltype (std::begin (std::declval <iterable> ()))>>
{
    static constexpr bool value = true;
};

template <typename iterable>
constexpr bool is_iterable_v = is_iterable <iterable>::value;

// visit elements of a tuple

template <size_t Index, typename visitor, typename ...types>
void visit_tuple (std::tuple <types...> const & Tuple, visitor && Visitor)
{
    Visitor (std::get <Index> (Tuple));

    constexpr auto nextIndex = Index + 1;

    if constexpr (nextIndex < sizeof... (types))
        visit_tuple <nextIndex> (Tuple, Visitor);
}

// this function generically walks the elements of a container, with an overload for tuples and pairs

template <typename container, typename visitor>
std::enable_if_t <is_iterable_v <container>>
visit_elements (container const & Container, visitor && Visitor)
{
    for (auto && Element: Container)
        Visitor (Element);
}

template <typename visitor, typename ...element_types>
void visit_elements (std::tuple <element_types...> const & Tuple, visitor && Visitor)
{
    if constexpr (sizeof... (element_types) > 0)
        visit_tuple <0> (Tuple, Visitor);
}

template <typename visitor, typename first_type, typename second_type>
void visit_elements (std::pair  <first_type, second_type> const & Pair, visitor && Visitor)
{
    Visitor (Pair.first);
    Visitor (Pair.second);
}

// type trait for testing if a value is "visitable"

struct dummy_visitor { template <typename type> void operator () (type &&); };

template <typename container, typename tag = void>
struct is_visitable
{
    static constexpr bool value = false;
};

template <typename container>
struct is_visitable <container, std::void_t <decltype (visit_elements (std::declval <container> (), dummy_visitor()))>>
{
    static constexpr bool value = true;
};

template <typename container>
constexpr bool  is_visitable_v =  is_visitable <container>::value;

// this function walks each item and either emits it or recurses into it

template <typename iterable>
bool join_impl (std::ostream & os, char delim, bool emitted_anything, iterable const & Iterable)
{
  using std::begin;
  using std::end;

  visit_elements (Iterable, [&] (auto && Element) {

    if constexpr (!is_visitable_v <decltype (Element)>)
    {
        if (emitted_anything)
          os << delim;

        os << Element;

        emitted_anything = true;
    }
    else
    {
      emitted_anything = join_impl (os, delim, emitted_anything, Element);
    }

  });

  return emitted_anything;
}

// these are wrappers to adapt join_impl for different use cases

template <typename container>
struct joiner
{
    char delim;
    container const & Container;

    operator std::string () const { return to_string <char> (); }

    template <typename char_t>
    std::basic_string <char_t> to_string () const;
};

template <typename container>
std::ostream & operator << (std::ostream & os, joiner <container> j)
{
    bool emitted_anything = false;
    join_impl (os, j.delim, emitted_anything, j.Container);
    return os;
}

template <typename container>
template <typename char_t>
std::basic_string <char_t> joiner <container>::to_string () const
{
    std::ostringstream os;
    os << *this;
    return os;
}

template <typename container>
std::enable_if_t <is_visitable_v <container>, joiner <container>>
join (char delim, container const & Container)
{
    return joiner <container> { delim, Container };
}

// test the streaming use case

int main ()
{
    std::vector <std::vector <std::tuple <int, float>>> x {
        { { 1, 1.0f }, { 2, 2.0f }},
        { { 3, 3.0f }, { 4, 4.0f }},
    };

    std::cout << join (',', x) << std::endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
//这允许我们测试一个元素是否应该递归到
模板
结构是不可编辑的
{
静态constexpr bool值=false;
};
模板
结构是不可编辑的
{
静态constexpr布尔值=真;
};
模板
constexpr bool is_iterable_v=is_iterable::value;
//访问元组的元素
模板
无效访问(std::tuple const和tuple,visitor和visitor)
{
访问者(std::get(Tuple));
constexpr auto nextIndex=Index+1;
if constexpr(nextIndex0)
访问组(tuple,Visitor);
}
模板
无效访问元素(标准::对常量和对、访问者和访问者)
{
访客(配对第一);
访客(配对第二);
}
//输入用于测试值是否为“可访问”的特征
struct dummy_visitor{template void操作符()(type&);};
模板
结构是可访问的
{
静态constexpr bool值=false;
};
模板
结构是可访问的
{
静态constexpr布尔值=真;
};
模板
constexpr bool is_visitable_v=is_visitable::value;
//此函数遍历每个项,并将其发射或递归到其中
模板
bool join_impl(标准::ostream&os、char delim、bool emission_anything、iterable const&iterable)
{
使用std::begin;
使用std::end;
访问元素(Iterable,[&](自动和元素){
如果constexpr(!可访问)
{
如果(有什么)

os以下是我将如何处理它的示意图:

#include <iostream>
#include <algorithm>
#include <type_traits>
#include <sstream>
#include <vector>
#include <tuple>

// this allows us to test if a element should be recursed into

template <typename iterable, typename tag = void>
struct is_iterable
{
    static constexpr bool value = false;
};

template <typename iterable>
struct is_iterable <iterable, std::void_t <decltype (std::begin (std::declval <iterable> ()))>>
{
    static constexpr bool value = true;
};

template <typename iterable>
constexpr bool is_iterable_v = is_iterable <iterable>::value;

// visit elements of a tuple

template <size_t Index, typename visitor, typename ...types>
void visit_tuple (std::tuple <types...> const & Tuple, visitor && Visitor)
{
    Visitor (std::get <Index> (Tuple));

    constexpr auto nextIndex = Index + 1;

    if constexpr (nextIndex < sizeof... (types))
        visit_tuple <nextIndex> (Tuple, Visitor);
}

// this function generically walks the elements of a container, with an overload for tuples and pairs

template <typename container, typename visitor>
std::enable_if_t <is_iterable_v <container>>
visit_elements (container const & Container, visitor && Visitor)
{
    for (auto && Element: Container)
        Visitor (Element);
}

template <typename visitor, typename ...element_types>
void visit_elements (std::tuple <element_types...> const & Tuple, visitor && Visitor)
{
    if constexpr (sizeof... (element_types) > 0)
        visit_tuple <0> (Tuple, Visitor);
}

template <typename visitor, typename first_type, typename second_type>
void visit_elements (std::pair  <first_type, second_type> const & Pair, visitor && Visitor)
{
    Visitor (Pair.first);
    Visitor (Pair.second);
}

// type trait for testing if a value is "visitable"

struct dummy_visitor { template <typename type> void operator () (type &&); };

template <typename container, typename tag = void>
struct is_visitable
{
    static constexpr bool value = false;
};

template <typename container>
struct is_visitable <container, std::void_t <decltype (visit_elements (std::declval <container> (), dummy_visitor()))>>
{
    static constexpr bool value = true;
};

template <typename container>
constexpr bool  is_visitable_v =  is_visitable <container>::value;

// this function walks each item and either emits it or recurses into it

template <typename iterable>
bool join_impl (std::ostream & os, char delim, bool emitted_anything, iterable const & Iterable)
{
  using std::begin;
  using std::end;

  visit_elements (Iterable, [&] (auto && Element) {

    if constexpr (!is_visitable_v <decltype (Element)>)
    {
        if (emitted_anything)
          os << delim;

        os << Element;

        emitted_anything = true;
    }
    else
    {
      emitted_anything = join_impl (os, delim, emitted_anything, Element);
    }

  });

  return emitted_anything;
}

// these are wrappers to adapt join_impl for different use cases

template <typename container>
struct joiner
{
    char delim;
    container const & Container;

    operator std::string () const { return to_string <char> (); }

    template <typename char_t>
    std::basic_string <char_t> to_string () const;
};

template <typename container>
std::ostream & operator << (std::ostream & os, joiner <container> j)
{
    bool emitted_anything = false;
    join_impl (os, j.delim, emitted_anything, j.Container);
    return os;
}

template <typename container>
template <typename char_t>
std::basic_string <char_t> joiner <container>::to_string () const
{
    std::ostringstream os;
    os << *this;
    return os;
}

template <typename container>
std::enable_if_t <is_visitable_v <container>, joiner <container>>
join (char delim, container const & Container)
{
    return joiner <container> { delim, Container };
}

// test the streaming use case

int main ()
{
    std::vector <std::vector <std::tuple <int, float>>> x {
        { { 1, 1.0f }, { 2, 2.0f }},
        { { 3, 3.0f }, { 4, 4.0f }},
    };

    std::cout << join (',', x) << std::endl;
}
#包括
#包括
#包括
#包括
#包括
#包括
//这允许我们测试一个元素是否应该递归到
模板
结构是不可编辑的
{
静态constexpr bool值=false;
};
模板
结构是不可编辑的
{
静态constexpr布尔值=真;
};
模板
constexpr bool is_iterable_v=is_iterable::value;
//访问元组的元素
模板
无效访问(std::tuple const和tuple,visitor和visitor)
{
访问者(std::get(Tuple));
constexpr auto nextIndex=Index+1;
if constexpr(nextIndex0)
访问组(tuple,Visitor);
}
模板
无效访问元素(标准::对常量和对、访问者和访问者)
{
访客(配对第一);
访客(配对第二);
}
//输入用于测试值是否为“可访问”的特征
struct dummy_visitor{template void操作符()(type&);};
模板
结构是可访问的
{
静态constexpr bool值=false;
};
模板
结构是可访问的
{
静态constexpr布尔值=真;
};
模板
constexpr bool is_visitable_v=is_visitable::value;
//此函数遍历每个项,并将其发射或递归到其中
模板
bool join_impl(标准::ostream&os、char delim、bool emission_anything、iterable const&iterable)
{
使用std::begin;
使用std::end;
访问元素(Iterable,[&](自动和元素){
如果constexpr(!可访问)
{
如果(有什么)

os我成功地清除了错误。我只是错误地计算了一个函子。我的初衷是让它也能用于数组,但事实并非如此。无论如何,这基本上是一个用于任意维csv的csv编写器

#include <iostream>
#include <typeinfo>
#include <vector>

template <typename RAI>
std::string string_join(RAI begin, RAI end, std::string delimiter) {
    if (begin == end) { return ""; }
    std::string joint = std::to_string(*begin);
    begin++;
    for (; begin != end; begin++) {
        joint += delimiter + std::to_string(*begin);
    }
    return joint;
}

template <typename RAI, int depth>
struct string_join_recursive {
    std::string operator()(RAI iterator, std::string *delimiters, int *dimensions) {
        typedef typename std::iterator_traits<RAI>::value_type::iterator value_iterator_type;
        std::string joint = string_join_recursive<value_iterator_type, depth-1>()(std::begin(*iterator), delimiters+1, dimensions+1);
        iterator++;
        for (int i=1; i<*dimensions; i++) {
            joint += *delimiters + string_join_recursive<value_iterator_type, depth-1>()(std::begin(*iterator), delimiters+1, dimensions+1);
            iterator++;
        }
        return joint;
    }
};

template <typename RAI>
struct string_join_recursive<RAI,1> {
    std::string operator()(RAI iterator, std::string *delimiters, int *dimensions) {
        return string_join(iterator, iterator + *dimensions, *delimiters);
    }
};

int main() {
    std::vector<int> a = {1,2,3};
    std::vector<int> b = {4,5,6};
    std::vector<int> c = {7,8,9};
    std::vector<int> d = {10,11,12};
    std::vector<std::vector<int>> e = {a,b};
    std::vector<std::vector<int>> f = {c,d};
    std::vector<std::vector<std::vector<int>>> g = {e,f};
    std::string delimiters[3] = {"\n",";",","};
    int dimensions[3] = {2, 2, 3};
    std::cout << string_join_recursive<std::vector<std::vector<std::vector<int>>>::iterator, 3>()(g.begin(), delimiters, dimensions) << std::endl;
}
#包括
#包括
#包括
模板
std::string_join(RAI开始、RAI结束、std::string分隔符){
如果(begin==end){return”“;}
标准::管柱接头=标准::至管柱(*开始);
begin++;
for(;begin!=end;begin++){
joint+=分隔符+std::to_字符串(*begin);
}
回位接头;
}
模板
结构字符串\u连接\u递归{
std::string操作符()(RAI迭代器,std::string*分隔符,int*维度){
typedef typename std::iterator_traits::value_type::iterator value_iterator_type;
std::string joint=string\u join\u recursive()(std::begin(*迭代器),分隔符+1,维度+1);
迭代器++;

对于(int i=1;i我成功地清除了错误。我只是错误地计算了一个函子。我的初衷是让它对数组也起作用,但事实并非如此。无论如何,这基本上是一个用于任意维csv的csv编写器

#include <iostream>
#include <typeinfo>
#include <vector>

template <typename RAI>
std::string string_join(RAI begin, RAI end, std::string delimiter) {
    if (begin == end) { return ""; }
    std::string joint = std::to_string(*begin);
    begin++;
    for (; begin != end; begin++) {
        joint += delimiter + std::to_string(*begin);
    }
    return joint;
}

template <typename RAI, int depth>
struct string_join_recursive {
    std::string operator()(RAI iterator, std::string *delimiters, int *dimensions) {
        typedef typename std::iterator_traits<RAI>::value_type::iterator value_iterator_type;
        std::string joint = string_join_recursive<value_iterator_type, depth-1>()(std::begin(*iterator), delimiters+1, dimensions+1);
        iterator++;
        for (int i=1; i<*dimensions; i++) {
            joint += *delimiters + string_join_recursive<value_iterator_type, depth-1>()(std::begin(*iterator), delimiters+1, dimensions+1);
            iterator++;
        }
        return joint;
    }
};

template <typename RAI>
struct string_join_recursive<RAI,1> {
    std::string operator()(RAI iterator, std::string *delimiters, int *dimensions) {
        return string_join(iterator, iterator + *dimensions, *delimiters);
    }
};

int main() {
    std::vector<int> a = {1,2,3};
    std::vector<int> b = {4,5,6};
    std::vector<int> c = {7,8,9};
    std::vector<int> d = {10,11,12};
    std::vector<std::vector<int>> e = {a,b};
    std::vector<std::vector<int>> f = {c,d};
    std::vector<std::vector<std::vector<int>>> g = {e,f};
    std::string delimiters[3] = {"\n",";",","};
    int dimensions[3] = {2, 2, 3};
    std::cout << string_join_recursive<std::vector<std::vector<std::vector<int>>>::iterator, 3>()(g.begin(), delimiters, dimensions) << std::endl;
}
#包括
#包括
#包括
模板
std::string_join(RAI开始、RAI结束、std::string分隔符){
如果(begin==end){return”“;}
标准::管柱接头=标准::至管柱(*开始);
begin++;
for(;begin!=end;begin++){
joint+=分隔符+std::to_字符串(*begin);
}
回位接头;
}
模板
结构字符串\u连接\u递归{
圣