C++ 无虚拟或遗传的多态载体
我正在尝试实现一个向量,它可以包含几种类型的元素,并且可以对所有类型的元素应用一个函数。使用基类、虚拟函数和继承很容易做到这一点,但我不想使用它。以下是我到目前为止的成就:C++ 无虚拟或遗传的多态载体,c++,templates,c++11,polymorphism,variadic-templates,C++,Templates,C++11,Polymorphism,Variadic Templates,我正在尝试实现一个向量,它可以包含几种类型的元素,并且可以对所有类型的元素应用一个函数。使用基类、虚拟函数和继承很容易做到这一点,但我不想使用它。以下是我到目前为止的成就: #include <iostream> #include <vector> #include <tuple> // this will be my new polymorphic vector; template<typename... Ts> class myvector
#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>();
}
#包括
#包括
#包括
//这将是我的新多态载体;
模板
类myvector{
std::元组向量;
模板
对每个()无效{
}
模板
对每个()无效{
std::vector&vector=std::get(vectors);
对于(X&X:vector){
趣味趣味;
乐趣(x);
}
每个人都有一张照片;
}
公众:
模板
无效推回(施工T&T){
std::vector&vector=std::get(vectors);
向量。推回(t);
}
模板
void pop_back(){
std::vector&vector=std::get(vectors);
vector.pop_back();
}
/*这里我想传递一个函数,或者函数对象
*可以扩展到所有底层类型。我更喜欢
*给出一个函数名,该函数名对Ts中的所有类型都有实现
*/
模板
void ForEach(){
每个人都有一张照片;
}
};
结构foo{
};
结构条{
};
模板
空隙法(T&T);
模板
无效方法(foo&b){
std::cout一种常见的解决方案是将函数对象与一组操作符()一起使用。
:
如果我们想添加对此类函数对象的支持,我们可以定义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;
}
要传递一组重载的自由函数,我们可以将它们封装在函数对象中(感谢@Yakk的建议):
struct方法
{
模板
void运算符()(Ts&…Ts)常量
{method(std::forward(ts)…);}
};
在C++1y中,可以使用多态lambda使用较少的样板创建这样的函数对象类型:
[](auto&&... pp)
{ method( std::forward<decltype(pp)>(pp)... ); }
[](自动和…pp)
{method(std::forward(pp)…);}
首先,你应该为你使用的语言添加标签(非常肯定是C++,但我不想假设)第二,解释为什么你不想用语言来解决这个问题?也许是因为作业分配明确地指示你不要这样做?谢谢C++提示。我是舒尔,它在那里,秘密地被解雇了。其次:不,这不是一个家庭作业。只是因为我不喜欢指针。以C++的任何形式。我喜欢保持所有的平面数据。按类型排序通常是性能的好事情。你的<代码>前缀<代码>函数是为了操作所有存储的对象?按顺序排序?是的,对所有存储的对象进行操作,顺序不重要。你可能想要一些类似于代码>模板空洞的东西。(Fun&&Fun);
用于单一类型版本,而模板void ForEach(Fun&&Fun){int dummy[]={(对于每个(Fun),0)…};(void)dummy;};
用于所有类型版本。这用于具有一组重载运算符()的函数对象
。谢谢,这是可行的,但我仍然有一些问题。这是可行的:vec.ForEach([](auto t){method(t);});但这不是:vec.ForEach(method);我的意思是两者都可以用()两者都有一个模板参数,为什么第二个失败?@ArneForEach
需要为其函数参数推断一个类型。method
是函数模板的名称;这样的东西没有(唯一的)类型。当您试图传递一组重载函数的名称时,会出现类似的问题。没有重载函数的类型集,只有一个指向特定函数的引用/指针。@Arne lambda表达式具有类类型,我的答案中呈现的多态lambda本质上会导致创建类似方法\u t lambda表达式就是该类型的实例。
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;
}
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;
}
struct method_t
{
template<class... Ts>
void operator()(Ts&&... ts) const
{ method( std::forward<Ts>(ts)... ); }
};
[](auto&&... pp)
{ method( std::forward<decltype(pp)>(pp)... ); }