我正在嘗試將一些代碼從 Python 移植到 C 。Python 代碼具有一個函式foo,該函式可以采用具有可變串列深度的整數嵌套串列。例如,這些是對 foo 的合法函式呼叫:
foo([ [], [[]], [ [], [[]] ] ])
foo([1])
foo([ [1], [2, 3, [4, 5]], [ [6], [7, [8, 9], 10] ] ])
對于可以接受這種引數的 C 方法,方法簽名應該是什么?
uj5u.com熱心網友回復:
這是我的看法
#include <iostream>
#include <variant>
#include <vector>
// A class containing either a T or a nest<T>
template<class T>
struct nest {
auto cbegin() const { return d.cbegin(); }
auto cend() const { return d.cend(); }
auto begin() const { return d.cbegin(); }
auto end() const { return d.cend(); }
auto begin() { return d.begin(); }
auto end() { return d.end(); }
std::vector<std::variant<T, nest<T>>> d;
};
namespace detail {
template<class... Ts> // helper type for visitor
struct overloaded : Ts... { using Ts::operator()...; };
template<class... Ts> // deduction guide for helper type
overloaded(Ts...) -> overloaded<Ts...>;
template<class T>
void foo_helper(const std::variant<T, nest<T>>& n) {
std::visit(overloaded {
[](const T& v) { std::cout << v; },
[](const nest<T>& v) { foo(v); }
}, n);
};
} // namespace detail
template<class T>
void foo(const nest<T>& list) {
auto it = list.begin();
std::cout << '[';
if(it != list.end()) {
detail::foo_helper(*it);
for( it; it != list.end(); it) {
std::cout << ',';
detail::foo_helper(*it);
}
}
std::cout << ']';
}
int main() {
std::cout << "[[1],[2,3,[4,5]],[[6],[7,[8,9],10]]] <- what we aim for\n";
foo(nest<int>{{nest<int>{{1}},
nest<int>{{2, 3, nest<int>{{4, 5}}}},
nest<int>{{nest<int>{{6}},
nest<int>{{7, nest<int>{{8,9}}, 10}}}}}} );
}
輸出:
[[1],[2,3,[4,5]],[[6],[7,[8,9],10]]] <- what we aim for
[[1],[2,3,[4,5]],[[6],[7,[8,9],10]]]
uj5u.com熱心網友回復:
我最終用這個資料結構解決了它:
using tIntList = std::vector<int>;
using tListOrInt = std::variant<tIntList, int>;
class VariableDepthList {
public:
using tListOfNestedLists = std::vector<VariableDepthList>;
using tListElement = std::variant<tListOfNestedLists, tIntList, int>;
explicit VariableDepthList(tListElement _element) : element(std::move(_element)) {};
tListElement element;
};
然后是 foo 的各種多載,它們采用每種變體型別。
這是一個構建串列的示例[ [], [[]], [ [], [[]] ] ]:
using tListOfNestedLists = VariableDepthList::tListOfNestedLists;
VariableDepthList deep_list(tListOfNestedLists{
VariableDepthList(tIntList{}), // []
VariableDepthList(tListOfNestedLists{VariableDepthList(tIntList{})}), // [[]]
VariableDepthList(tListOfNestedLists{
VariableDepthList(tIntList{}), // []
VariableDepthList(tListOfNestedLists{VariableDepthList(tIntList{})}) // [[]]
})
});
uj5u.com熱心網友回復:
這是一種定義和使用非常簡單的方法:
#include <variant>
#include <vector>
struct VariableDepthList : std::variant<std::vector<VariableDepthList>, int> {
private:
using base = std::variant<std::vector<VariableDepthList>, int>;
public:
using base::base;
VariableDepthList(std::initializer_list<VariableDepthList> v) : base(v) {}
};
這是基于您的型別是int(相同型別)的一個或串列這一事實,添加一個 initializer_list 建構式只是為了便于使用。
您可能還想添加一些輔助函式,例如is_vector()/ is_value()。
這是一個使用它的例子:
#include <iostream>
void foo(const VariableDepthList& v) {
// Use like a variant. This is a print function
if (auto* as_vector = std::get_if<std::vector<VariableDepthList>>(&v)) {
if (as_vector->empty()) {
std::cout << "[]";
return;
}
std::cout << "[ ";
bool first = true;
for (const auto& el : *as_vector) {
if (!first) {
std::cout << ", ";
}
first = false;
foo(el);
}
std::cout << " ]";
} else {
auto* as_int = std::get_if<int>(&v);
std::cout << *as_int;
}
}
int main() {
foo({});
std::cout << '\n';
foo({ 1 });
std::cout << '\n';
foo({ {}, {{}}, { {}, {{}} } });
foo( {{1},{2,3,{4,5}},{{6},{7,{8,9},10}}} );
std::cout << '\n';
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/388768.html
下一篇:C 元件和空指標
