我有两组课程,比如说集A = {a1, a2, a3}
来自Asuper
,B = {b1, b2}
全部来自Bsuper
,只有包含A和B的类可以可以一起使用(例如,a1和b2,或a3和b1;它们具有逻辑依赖性)。如何通过适当的课堂设计将此信息传达给用户?
一种方法是让枚举与每个类相关联并将它们呈现在某个地方。例如:
class LogicalGrouping{
enum gr1{A1, A2, A3};
enum gr2{B1, B2};
Asuper *a;
Bsuper *b;
setA(Asuper *a); //user can now manually check the types in gr1 and assign
setB(Bsuper *b);
};
但在我看来,这非常难看。一个人必须手动解码枚举的含义并分配它们。我想要像classlist {a1, a2, a3};
这样的类列表。
有更清洁的方法吗?
答案 0 :(得分:1)
创建两个接口IA和IB让所有A实现IA并且所有B实现IB然后创建继承自IA和IB的第三接口IAB。这将确保您拥有其中一个。
当你的班级用户想要使用你的班级时,他需要从IAB继承,迫使他选择一个A和一个B.
答案 1 :(得分:1)
这花了很长时间,但这是我提出的代码,基于@TartanLlama的建议(或多或少):
#include <iostream>
#include <cassert>
#include <type_traits>
#include <typeinfo>
#include <string>
//--- The class hierarchy
struct A{ virtual std::string name() const{ return "A";} };
struct B{ virtual std::string name() const{ return "B";} };
template <int i> struct An : A
{
virtual std::string name() const{ return A::name() + std::to_string(i);}
};
template <int i> struct Bn : B
{
virtual std::string name() const{ return B::name() + std::to_string(i);}
};
template <int i> struct AnBn : An<i>, Bn<i>
{
virtual std::string name() const{ return An<i>::name() + Bn<i>::name(); }
};
template <int i,int j> struct AnBm : An<i>, Bn<j>
{
virtual std::string name() const{ return An<i>::name() + Bn<j>::name(); }
};
//--- End of class hierarchy
//--- The magic that determines whether A/B is base of
template <class T> using A_is_base_of =
std::is_base_of<A,typename std::remove_reference<T>::type>;
template <class T> using B_is_base_of =
std::is_base_of<B,typename std::remove_reference<T>::type>;
template <class T>
struct AB_is_base_of
{
const static bool value = A_is_base_of<T>::value && B_is_base_of<T>::value;
typedef typename std::integral_constant<bool,value>::type type;
};
//--- A tester - requires T has member function name... just for now...
struct IsAB_BaseOf
{
template <class T>
static void test(T&& value)
{
return test(std::forward<T>(value),
typename AB_is_base_of<T>::type());
}
private: template <class T>
static void test(T&& value, std::true_type)
{
std::cout << value.name() << " derives from both A and B" << std::endl;
}
private: template <class T>
static void test(T&& value, std::false_type)
{
std::cout << value.name() << " does not derive from both A and B" << std::endl;
}
};
template <class T>
bool ab_IsBaseOf( T&& type )
{
return AB_is_base_of<T>::value;
}
int main() {
assert(!ab_IsBaseOf(An<0>()));
assert(!ab_IsBaseOf(Bn<0>()));
assert(!ab_IsBaseOf(Bn<0>()));
assert(!ab_IsBaseOf(An<0>()));
assert(!ab_IsBaseOf(An<0>()));
assert(!ab_IsBaseOf(Bn<0>()));
assert(ab_IsBaseOf(AnBn<0>()));
assert(ab_IsBaseOf(AnBm<0,1>()));
IsAB_BaseOf::test(AnBm<0,1>());
IsAB_BaseOf::test(An<0>());
IsAB_BaseOf::test(Bn<0>());
}
Output:
A0B1 derives from both A and B
A0 does not derive from both A and B
B0 does not derive from both A and B
基本上:
这个想法是,如果A和B是T的基础,ab_IsBaseOf返回true。
编辑:
可以毫不费力地从元函数创建一个类型,您可以将其用作函数的参数,只有当T具有正确的类型(称为标签调度)时才会调用该函数。
编辑:
我现在修改了呈现的源代码,使用标签调度根据类型T是否从A和B派生来选择一个函数,根据我的理解,这是OP想要的。欢迎提出问题。