gpt4 book ai didi

c++ - 没有虚拟或继承的多态 vector

转载 作者:搜寻专家 更新时间:2023-10-31 01:43:25 26 4
gpt4 key购买 nike

我正在尝试实现一个 vector ,它可以采用多种类型的元素,并且可以对所有元素应用一个函数。这很容易用基类、虚函数和继承来完成,但我明确地不想使用它。这是我到目前为止的进展情况:

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

// this will be my new polymorphic vector;
template<typename... Ts>
class myvector {
std::tuple<std::vector<Ts>...> vectors;

template <template<typename> class funtype>
void for_each() {
}

template <template<typename> class funtype, typename X, typename... Xs>
void for_each() {
std::vector<X>& vector = std::get<std::vector<X>>(vectors);
for ( X& x : vector ) {
funtype<X> fun;
fun(x);
}
for_each<funtype, Xs...>();
}

public:
template <typename T>
void push_back(const T& t) {
std::vector<T>& vector = std::get<std::vector<T>>(vectors);
vector.push_back(t);
}

template <typename T>
void pop_back() {
std::vector<T>& vector = std::get<std::vector<T>>(vectors);
vector.pop_back();
}

/* here I would like to pass a function, or function object that
* can be expanded to all underlying types. I would prefer to just
* give a function name, that has an implementation to all types in Ts
*/
template <template<typename> class funtype>
void ForEach() {
for_each<funtype,Ts...>();
}
};


struct foo {
};

struct bar {
};

template <typename T>
void method(T& t);

template<>
void method(foo& b) {
std::cout << "foo" << std::endl;
}

template<>
void method(bar& b) {
std::cout << "bar" << std::endl;
}

int main()
{
myvector<foo,bar> mv;
mv.push_back( foo{} );
mv.push_back( bar{} );
mv.ForEach<method>();
}

目前我有点卡住了,我希望你能给我一些建议,告诉我如何走得更远。

最佳答案

一个常见的解决方案是使用带有一组operator()的函数对象:

struct my_fun_type
{
void operator()(foo&) const
{ std::cout << "foo\n"; }

void operator()(bar&) const
{ std::cout << "bar\n"; }
};

这允许将“一组”重载函数传递给算法、状态,并且使用起来相当方便:

my_algorithm(my_fun_type{});

如果我们想添加对此类函数对象的支持,我们可以按如下方式定义 ForEach:

template <typename Elem, typename Fun>
void for_each(Fun&& fun) {
std::vector<Elem>& vector = std::get<std::vector<Elem>>(vectors);
for ( Elem& e : vector ) {
fun(x);
}
}

template <typename Fun>
void ForEach(Fun&& fun) {
int dummy[] = { 0, (for_each<Ts>(fun), 0)... };
(void)dummy;
}

dummy 是为 Ts 中的所有类型调用 for_each 的技巧。 (void)dummy 旨在抑制编译器警告(永远不会读取 dummy)。

您可以在其他问答中了解有关此技术的更多信息,例如 that one .

Fun&& 不是右值引用,而是 universal reference .


请注意,上面的示例不同于许多标准库算法,后者按值获取函数对象:

template <typename Elem, typename Fun>
void for_each(Fun fun) {
std::vector<Elem>& vector = std::get<std::vector<Elem>>(vectors);
std::for_each(vector.begin(), vector.end(), std::move(fun));
}

template <typename Fun>
void ForEach(Fun fun) {
int dummy[] = { 0, (for_each<Ts>(fun), 0)... };
(void)dummy;
}

要传递一组重载的自由函数,我们可以将它们包装在一个函数对象中(感谢@Yakk 的建议):

struct method_t
{
template<class... Ts>
void operator()(Ts&&... ts) const
{ method( std::forward<Ts>(ts)... ); }
};

在 C++1y 中,可以使用多态 lambda 使用更少的样板创建这样的函数对象类型:

[](auto&&... pp)
{ method( std::forward<decltype(pp)>(pp)... ); }

关于c++ - 没有虚拟或继承的多态 vector ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25190725/

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