[英]C++ standard paragraph about member template specialization of unspecialized template
[英]C++ list of unspecialized template type objects?
我一直在寻找有关此主题的问题,尽管也有类似的问题,但没有一个能真正解决我的问题。 所以,我去。
假设我有一个模板类型F,并且我将一系列专门化声明为另一个对象的成员变量:
F<A> a;
F<B> b;
.
.
.
稍后,我想遍历这些对象并执行在任何F实例上定义的操作。
因此,我的冲动是创建一个std :: list <F>,但这不起作用。
有没有一种方法可以创建类型为F的对象的列表,即不指定template参数呢?
我的预感不是,不是C ++,但是希望我错了。
不幸的是,答案是否定的 。 在C ++中,您不能拥有一个异构的不相关对象的容器,并且同一模板的不同实例是不相关的。
使其起作用的唯一方法是使用某种形式的类型擦除。 最惯用的方法是使用继承和虚函数,并将指向基础对象的指针放入列表中。
就C ++而言,模板类或结构的两个不同模板实例是完全独立的类型,彼此之间没有任何关系。 例如, std::vector<int>
和std::vector<char>
是单独的类型; 两者都不来自对方或任何共同基础。 两种类型都来自同一模板的实例化这一事实并没有在这些类型之间创建语义关系。 从这种意义上(并且仅这种意义上),您可能会想到诸如预处理器宏之类的模板,这些模板在编译前已扩展为声明新的无关类型。
但是,您可以使用继承自行创建这样的关系,就像使用任何非模板类型一样:
#include <iostream>
struct foo_base {
virtual void print() = 0;
};
template <typename T>
struct foo : foo_base {
foo(T data) : data(data) {}
virtual void print() override {
std::cout << data << std::endl;
}
private: T data;
};
void example() {
foo<int> f(42);
f.print();
}
在这里, foo<int>
和foo<char>
是单独的类型(作为foo<>
模板的不同实例化),但是所有foo<>
实例化都源自foo_base
。 (当然,除非您提供foo<>
的显式特化,它不是从foo_base
派生的...)
除非所有F<X>
都独立于某个独立于X
公共基类派生,否则只有使用类型擦除或异构容器才有可能实现。
如果它们都继承自Foo
,那么您当然可以将它们作为Foo&
/ Foo*
进行迭代,但是我想您知道这一点。
如果它们的类型不同,则标准容器无法容纳它们,因为它们是同质的-所有元素都具有相同的类型。 可能有一些带有异构容器的库,但是在STL中,您只能使用std::variant
或std::any
来模仿。
最后一个办法,我能想象这工作了-我不建议这一点-是通过创建封装类的派生类的F<X>
S(可变参数模板)和编码调用转换成层次结构,ST每˚F s
foo`被称为
由于涉及到更多,这里是一个示例:
#include <iostream>
template <class X>
class Foo {
X mem;
public:
explicit Foo(X arg) : mem(arg) {}
void foo() {
std::cout << mem;
}
};
template <class X, class ...Xs> class Holder;
template <class X>
class Holder<X> {
X member;
public:
Holder(X arg) : member(std::forward<decltype(arg)>(arg)) {}
void call() {
member.foo();
}
};
template <class X, class ...Ys>
class Holder : public Holder<Ys...> {
X member;
public:
Holder(X arg, Ys ...args) : Holder<Ys...>(std::forward<decltype(args)>(args)...), member(std::forward<decltype(arg)>(arg)) { }
void call() {
member.foo();
Holder<Ys...>::call();
}
};
int main() {
// omitting the template-args requires c++17 deduction guides
Holder holder(Foo(4), Foo(" Hello "), Foo(7L), Foo(" World "));
holder.call();
std::cout << std::endl;
}
您也许可以猜测,这通常不是您想要的,因为它非常复杂。 实际上,我省略了一些事情,例如完美地传递参数以将其保持在最小限度,希望有人可以理解这个概念。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.