C++ 可变模板双端封装解决方案
下面的代码是编译的,因为我假设C++ 可变模板双端封装解决方案,c++,templates,c++11,variadic,C++,Templates,C++11,Variadic,下面的代码是编译的,因为我假设Object本身的parent没有父对象 template <typename Parent, typename T, typename... Rest> struct Object { T item; // T is item's type, while Parent is parent's item's type. Object<T, Rest...>* child; // child's item type is t
Object
本身的parent
没有父对象
template <typename Parent, typename T, typename... Rest>
struct Object {
T item; // T is item's type, while Parent is parent's item's type.
Object<T, Rest...>* child; // child's item type is the first type from Rest...
Object<void, Parent, T, Rest...>* parent;
Object(const T& t) : item(t) {}
void setChild (Object<T, Rest...>* c) {
child = c;
child->setParent(this);
}
void setParent (Object<void, Parent, T, Rest...>* p) {parent = p;}
};
template <typename Parent, typename T>
struct Object<Parent, T> { // Has no child.
T item;
Object<void, Parent, T>* parent;
Object(const T& t) : item(t) {}
void setParent (Object<void, Parent, T>* p) {parent = p;}
};
template <typename... Args>
using ObjectWithNoParent = Object<void, Args...>;
int main() {
ObjectWithNoParent<int, char, double> object(2);
Object<int, char, double> child('r');
object.setChild(&child);
Object<char, double> grandChild(3.5);
// child.setChild(&grandChild); // Want this line to work.
}
模板
结构对象{
T item;//T是项的类型,而Parent是父项的项的类型。
Object*child;//子对象的项类型是Rest中的第一个类型。。。
对象*父对象;
对象(常量T&T):项(T){}
void setChild(对象*c){
child=c;
child->setParent(这个);
}
void setParent(Object*p){parent=p;}
};
模板
结构对象{//没有子对象。
T项;
对象*父对象;
对象(常量T&T):项(T){}
void setParent(Object*p){parent=p;}
};
模板
使用ObjectWithNoParent=Object;
int main(){
ObjectWithNoParent object(2);
对象子对象('r');
对象。setChild(&child);
对象孙子(3.5);
//setChild(&孙子);//希望此行正常工作。
}
我可以使用什么解决方法,以便用常规类型替换类型
void
?编译器必须能够知道一个参数包从何处开始,另一个参数包从何处结束。为此,您不可能直接询问,但有一个解决方法:使用另一个可变模板作为“包分隔符”
我们的目标是支持以下类型:
Object<pack<A, B>, C, pack<D, E>> foo;
无父类型的第一个包为空,无子类型的第二个包为空
由于不能通过变量参数“向后递归”,这就复杂了很多,因此具有父类型的类型会有点模糊。(不幸的是,
template struct foo
的方法不起作用,因为参数包必须是模板参数列表中的最后一个内容。)我们需要更多的帮助来获取并“剥离”变量包中的最后一个类型(更改pack,它没有做太多的工作,但它确实表明这是编译的,并且它断言父类型和子类型是我们所期望的。)需要明确的是:您希望初始化看起来如何?因为父级必须知道自己的父级
,最后的子级
将整个层次结构作为父级类型…@bolob。main中注释掉的行显示了我想要的内容。@Jarod42,所以如果我将孙级
作为对象孙子;
相反,那么整个事情最终将成为可能?但这将意味着包的两端都需要。
,笼统地说,不是吗(因此标题)?我明白了,我希望我记得稍后能给出一个完整的答案:@At Mooing Duck。是的,在我开车回家的时候,我也在想用一个整数来识别值类型。你可能也想看看cdhowie的解决方案,这不会强迫我们用眼睛来计算哪一个是值类型。谢谢你的出色解决方案和text-book解释。我测试了使用的第二个pack
是不需要的,因为我们知道第二个pack
从哪里开始(总是第一个pack
之后的第二个类型)。非常感谢!@prestokeys是的,这是真的。出于一些没有想到的原因。谢天谢地,这是一个简单的改变。
Object<pack<A>, B, pack<C, D, E>> foo_parent;
Object<pack<A, B, C>, D, pack<E>> foo_child;
// Helper template; needs no definition since we never instantiate it.
template <typename...> struct pack;
// Helper to allow us to obtain the last type from a pack.
template <typename> struct last_type_in_pack;
template <typename T>
struct last_type_in_pack<pack<T>>
{
typedef T type;
};
template <typename First, typename... Types>
struct last_type_in_pack<pack<First, Types...>>
: public last_type_in_pack<pack<Types...>> { };
// We need another helper to allow us to "peel off" the last type from a pack,
// turning pack<A, B, C> into pack<A, B> for example.
template <typename, typename> struct remove_last_type_from_pack_impl;
template <typename... Types, typename LastType>
struct remove_last_type_from_pack_impl<pack<Types...>, pack<LastType>>
{
typedef pack<Types...> type;
};
template <typename... TS1, typename T2, typename... TS2>
struct remove_last_type_from_pack_impl<pack<TS1...>, pack<T2, TS2...>>
: public remove_last_type_from_pack_impl<pack<TS1..., T2>, pack<TS2...>> { };
template <typename>
struct remove_last_type_from_pack;
template <typename... Types>
struct remove_last_type_from_pack<pack<Types...>>
: public remove_last_type_from_pack_impl<pack<>, pack<Types...>> { };
template <typename...> struct Object;
template <typename FirstParent, typename... ParentTypes,
typename T,
typename FirstChild, typename... ChildTypes>
struct Object<pack<FirstParent, ParentTypes...>, T, pack<FirstChild, ChildTypes...>>
{
// We'll shift the packs around T to define our child and parent types:
typedef Object<pack<FirstParent, ParentTypes..., T>,
FirstChild,
pack<ChildTypes...>> child_type;
typedef Object<
typename remove_last_type_from_pack<pack<FirstParent, ParentTypes...>>::type,
typename last_type_in_pack<pack<FirstParent, ParentTypes...>>::type,
pack<T, FirstChild, ChildTypes...>> parent_type;
T item;
child_type * child;
parent_type * parent;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
template <typename T, typename FirstChild, typename... ChildTypes>
struct Object<pack<>, T, pack<FirstChild, ChildTypes...>>
{
typedef Object<pack<T>, FirstChild, pack<ChildTypes...>> child_type;
T item;
child_type * child;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
template <typename FirstParent, typename... ParentTypes, typename T>
struct Object<pack<FirstParent, ParentTypes...>, T, pack<>>
{
typedef Object<
typename remove_last_type_from_pack<pack<FirstParent, ParentTypes...>>::type,
typename last_type_in_pack<pack<FirstParent, ParentTypes...>>::type,
pack<T>> parent_type;
T item;
parent_type * parent;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
template <typename T>
struct Object<pack<>, T, pack<>>
{
T item;
Object(T const & t) : item(t) { }
Object(T && t) : item(std::move(t)) { }
};
template <typename Arg, typename... Rest>
using ObjectWithNoParent = Object<pack<>, Arg, pack<Rest...>>;