考虑
struct AbstractClass {};
struct Derived1 : AbstractClass {
using type = int;
};
struct Derived2 : AbstractClass {
using type = char;
};
struct Derived3 : AbstractClass {
using type = bool;
};
int main() {
AbstractClass* a[] = {new Derived1, new Derived2, new Derived3};
}
如何从[0],[1],[2]获得type
?
这是我想要完成的事情。我想除此之外别无他法吗?
#include <iostream>
struct Object { virtual ~Object() = default; };
struct A : Object {};
struct B : Object {};
struct C : Object {};
struct AbstractClass {
virtual void take (Object*) {
std::cout << "Accepted.\n";
}
};
template <typename...> struct ObjectTypes;
template <typename First, typename... Rest>
struct ObjectTypes<First, Rest...> : ObjectTypes<Rest...> {
bool operator()(Object* o) const {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>::operator()(o);
}
};
template <>
struct ObjectTypes<> {
bool operator()(Object*) const {return false;}
};
struct Derived1 : AbstractClass {
using type = ObjectTypes<A,B>;
virtual void take (Object* o) override {
if (type()(o)) // This is why I want to use type from AbstractClass.
return AbstractClass::take(o);
std::cout << "Rejected.\n";
}
};
struct Derived2 : AbstractClass {
using type = ObjectTypes<A,C>;
virtual void take (Object* o) override {
if (type()(o))
return AbstractClass::take(o);
std::cout << "Rejected.\n";
}
};
struct Derived3 : AbstractClass {
using type = ObjectTypes<B,C>;
virtual void take (Object* o) override {
if (type()(o))
return AbstractClass::take(o);
std::cout << "Rejected.\n";
}
};
int main() {
AbstractClass* abs[] = {new Derived1, new Derived2, new Derived3};
A* a = new A;
B* b = new B;
C* c = new C;
for (AbstractClass* x : abs) {
x->take(a);
x->take(b);
x->take(c);
std::cout << "------------\n";
}
}
注意Derived1,Derived2,Derived3等中的重复...?因此,我最初的目标是在基类AbstractClass中完成所有工作。
答案 0 :(得分:1)
解决方案受到Wojciech Frohmberg建议的启发,但我不确定这是他的意思。我实际上不知道他的意思,我认为他的意思是其他的,并希望看到他的解决方案,并找出他实际上在说什么。
#include <iostream>
struct Object { virtual ~Object() = default; };
struct A : Object {};
struct B : Object {};
struct C : Object {};
template <typename...> struct ObjectTypes;
template <typename First, typename... Rest>
struct ObjectTypes<First, Rest...> : ObjectTypes<Rest...> {
bool operator()(Object* o) const {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>::operator()(o);
}
};
template <>
struct ObjectTypes<> {
bool operator()(Object*) const {return false;}
};
struct AbstractClass {
virtual void take (Object*) = 0;
template <typename... Ts> void takeHelper (Object* o, ObjectTypes<Ts...>&& types) {
if (types(o)) std::cout << "Accepted.\n"; // And now do whatever with o.
else std::cout << "Rejected.\n";
}
};
template <typename Derived>
struct AbstractClassCRTP : AbstractClass {
virtual void take (Object* o) override {
takeHelper(o, typename Derived::type{});
}
};
struct Derived1 : AbstractClassCRTP<Derived1> {
using type = ObjectTypes<A,B>;
};
struct Derived2 : AbstractClassCRTP<Derived2> {
using type = ObjectTypes<A,C>;
};
struct Derived3 : AbstractClassCRTP<Derived3> {
using type = ObjectTypes<B,C>;
};
int main() {
AbstractClass* abs[] = {new Derived1, new Derived2, new Derived3};
A* a = new A;
B* b = new B;
C* c = new C;
for (AbstractClass* x : abs) {
x->take(a);
x->take(b);
x->take(c);
std::cout << "------------\n";
}
}
输出:
Accepted.
Accepted.
Rejected.
------------
Accepted.
Rejected.
Accepted.
------------
Rejected.
Accepted.
Accepted.
答案 1 :(得分:1)
我更喜欢这样:
#include <iostream>
struct Object { virtual ~Object() = default; };
struct A : Object {};
struct B : Object {};
struct C : Object {};
struct SuperObjectType {
public:
virtual bool operator()(Object *o) const = 0;
};
template <typename First, typename... Rest>
struct ObjectTypes: SuperObjectType {
bool operator()(Object* o) const override {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>()(o);
}
};
template <typename OnlyOne>
struct ObjectTypes<OnlyOne>: SuperObjectType {
bool operator()(Object* o) const override {
return dynamic_cast<OnlyOne*>(o);
}
};
struct AbstractClass {
SuperObjectType *sot;
void take (Object* o) {
if ((*sot)(o)) {
std::cout << "ACCEPTED" << std::endl;
} else {
std::cout << "REJECTED" << std::endl;
}
}
};
struct Derived1 : AbstractClass {
Derived1() {
sot = new ObjectTypes<A,B>;
}
};
struct Derived2 : AbstractClass {
Derived2() {
sot = new ObjectTypes<A,C>;
}
};
struct Derived3 : AbstractClass {
Derived3() {
sot = new ObjectTypes<B,C>;
}
};
int main() {
AbstractClass* abs[] = {new Derived1, new Derived2, new Derived3};
A* a = new A;
B* b = new B;
C* c = new C;
for (AbstractClass* x : abs) {
x->take(a);
x->take(b);
x->take(c);
std::cout << "------------\n";
}
}
但我很高兴我给你的灵感;)
(可能)加速表现的次要替代方案:
template <typename First, typename... Rest>
struct ObjectTypes: ObjectTypes<Rest...> { // Derive from ObjectTypes<Rest...> instead.
virtual bool operator()(Object* o) const override {
if (dynamic_cast<First*>(o))
return true;
return ObjectTypes<Rest...>::operator()(o);
// So now ObjectTypes<Rest...>::operator() can be used, and thus avoid instantiation.
}
};
template <typename T>
struct ObjectTypes<T>: SuperObjectType {
virtual bool operator()(Object* o) const override {
return dynamic_cast<T*>(o);
}
};
因为ObjectTypes<T>
是从任何类型T的SuperObjectType派生的,所以ObjectTypes<First, Rest...>
也是从SuperObjectType派生的(通过派生自ObjectTypes<Last>
,Last是Rest中的最后一个类型。 ..)。所以一切仍然有效(经过测试)。