C++ 静态分派到具有聚合类型层次结构的正确成员方法

C++ 静态分派到具有聚合类型层次结构的正确成员方法,c++,c++11,C++,C++11,我已经编写了一个小型内部框架,其功能类似于: Group<ObjectA1, ObjectA2> groupA(data); Group<ObjectB> groupB(data); // Compiles, as desired: groupA.get<ObjectA1>(); groupA.get<ObjectA2>(); groupB.get<ObjectB>(); // Compilation errors (static

我已经编写了一个小型内部框架,其功能类似于:

Group<ObjectA1, ObjectA2> groupA(data);
Group<ObjectB> groupB(data);

// Compiles, as desired:
groupA.get<ObjectA1>();
groupA.get<ObjectA2>();
groupB.get<ObjectB>();

// Compilation errors (static asserts), as desired:
groupA.get<ObjectB>();
groupB.get<ObjectA1>();
groupB.get<ObjectA2>();
a组(数据);
b组(数据);
//根据需要编译:
groupA.get();
groupA.get();
groupB.get();
//编译错误(静态断言),根据需要:
groupA.get();
groupB.get();
groupB.get();
简而言之:可以将(可变)数量的对象分组在一起。然后可以查询组中的对象,这些对象的类型编码在组类型中。对于所有其他对象,会发生编译错误

接下来,我想用以下功能扩展它:

// ...continued...

using GroupA = Group<ObjectA1, ObjectA2>;
using GroupB = Group<ObjectB>;
AggregateGroup<GroupA, GroupB> group(groupA, groupB);

// Compiles, as desired
group.get<ObjectA1>();
group.get<ObjectA2>();
group.get<ObjectB>();

// Compilation error, as desired:
group.get<ObjectC>();
/…继续。。。
使用GroupA=Group;
使用GroupB=Group;
聚合组(A组、B组);
//根据需要编译
group.get();
group.get();
group.get();
//编译错误,根据需要:
group.get();
这可以推广到由其他组组成的组。运行时解决方案很简单,但我不知道如何在编译时做到这一点

问题:我们如何创建静态分派给正确成员的聚合类型层次结构


我当前实现的最低版本可以在

中找到。您的问题本质上是如何从
GroupA
内部的
AggregateGroup
获取实际的模板参数
ObjectA
。请参见下面的示例(为了便于理解,我简化了您的示例)

更新(可变模板) 您的代码已经非常接近解决方案。唯一需要更改的是删除wraper
ObjectRetriever

template<typename... Objects> class AggGroup;

template<typename Object, typename... Objects>
class AggGroup<Object, Objects...> : public Object, public AggGroup<Objects...>
   {
   public:
      explicit AggGroup(Context &context)
         : Object(context)
         , AggGroup<Objects...>(context)
         {
         }

      template<typename ObjectType>
      bool get()
         {
         static_assert(
            std::is_base_of<ObjectRetriever<ObjectType>, AggGroup>::value,
            "Object type not in object space"
            );

         return static_cast<ObjectRetriever<ObjectType> &>(*this).get();
         }
   };

template<>
class AggGroup<>
   {
   public:
      explicit AggGroup(Context &context)
         {
         }
   };
模板类分组;
模板
类AggGroup:公共对象,公共AggGroup
{
公众:
显式聚合组(上下文和上下文)
:对象(上下文)
,AggGroup(上下文)
{
}
模板
boolget()
{
静态断言(
std::是::value的_base,
“对象类型不在对象空间中”
);
返回static_cast(*this).get();
}
};
模板
类聚集群
{
公众:
显式聚合组(上下文和上下文)
{
}
};
试试下面的用法

using GroupA = ObjectGroup<ObjectA>;
using GroupB = ObjectGroup<ObjectB, ObjectC>;
AggGroup<GroupA, GroupB> group(context);
group.get<int>();     // not compile
group.get<ObjectB>(); // OK
使用GroupA=ObjectGroup;
使用GroupB=ObjectGroup;
AggGroup(上下文);
group.get();//不编译
group.get();//好啊

完整的代码。

您的问题本质上是如何从
GroupA
内部
AggregateGroup
获取实际的模板参数
ObjectA
。请参见下面的示例(为了便于理解,我简化了您的示例)

更新(可变模板) 您的代码已经非常接近解决方案。唯一需要更改的是删除wraper
ObjectRetriever

template<typename... Objects> class AggGroup;

template<typename Object, typename... Objects>
class AggGroup<Object, Objects...> : public Object, public AggGroup<Objects...>
   {
   public:
      explicit AggGroup(Context &context)
         : Object(context)
         , AggGroup<Objects...>(context)
         {
         }

      template<typename ObjectType>
      bool get()
         {
         static_assert(
            std::is_base_of<ObjectRetriever<ObjectType>, AggGroup>::value,
            "Object type not in object space"
            );

         return static_cast<ObjectRetriever<ObjectType> &>(*this).get();
         }
   };

template<>
class AggGroup<>
   {
   public:
      explicit AggGroup(Context &context)
         {
         }
   };
模板类分组;
模板
类AggGroup:公共对象,公共AggGroup
{
公众:
显式聚合组(上下文和上下文)
:对象(上下文)
,AggGroup(上下文)
{
}
模板
boolget()
{
静态断言(
std::是::value的_base,
“对象类型不在对象空间中”
);
返回static_cast(*this).get();
}
};
模板
类聚集群
{
公众:
显式聚合组(上下文和上下文)
{
}
};
试试下面的用法

using GroupA = ObjectGroup<ObjectA>;
using GroupB = ObjectGroup<ObjectB, ObjectC>;
AggGroup<GroupA, GroupB> group(context);
group.get<int>();     // not compile
group.get<ObjectB>(); // OK
使用GroupA=ObjectGroup;
使用GroupB=ObjectGroup;
AggGroup(上下文);
group.get();//不编译
group.get();//好啊

完整的代码。

一个最小的示例总是有用的。另外,如果您已经用GroupA和GroupB实例化了group,那么为什么希望ObjectC与之兼容呢?ObjectC是什么类型的?@Robinson:谢谢你的调查。关于您要求的澄清:(I)ObjectC是类型,既不在A组中,也不在B组中;(ii)您不希望它兼容,但您希望在编译时而不是在运行时知道任何错误。但是您的代码注释说,“编译错误,根据需要”。如果我的意图不够清楚,我很抱歉。我会尽力澄清的。给定一个组,我希望能够根据组的类型对请求的对象类型提供编译时错误检查。在组类型中的某个位置,支持的对象类型被编码。但我不确定如何正确利用这一点。我希望这更清楚。再次感谢您花时间。如果您能制作一个我们可以编译的最小示例,可能是基于或类似的,那将非常有用。最小示例总是有用的。另外,如果您已经用GroupA和GroupB实例化了group,那么为什么希望ObjectC与之兼容呢?ObjectC是什么类型的?@Robinson:谢谢你的调查。关于您要求的澄清:(I)ObjectC是类型,既不在A组中,也不在B组中;(ii)您不希望它兼容,但您希望在编译时而不是在运行时知道任何错误。但是您的代码注释说,“编译错误,根据需要”。如果我的意图不够清楚,我很抱歉。我会尽力澄清的。给定一个组,我希望能够根据组的类型对请求的对象类型提供编译时错误检查。在组类型中的某个位置,支持的对象类型被编码。但我不确定如何正确利用这一点。我希望这更清楚。再次感谢您花时间。如果您能提供一个我们可以编译的最小示例,可能是基于或类似的示例,这将非常有用。不幸的是,这不仅仅是一个简化。在您的示例中,类B实际上不是聚合组,因为它只包含一种类型。继续你的例子:如果你有B,你会如何为给定的C进行分派?本质上,U1只是U2的复制,你可以添加任意多的,只需重复
静态断言
行。虽然我认为没有必要,但我会将
U2
添加到我的例子中。我不这么认为