Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 可变模板双端封装解决方案_C++_Templates_C++11_Variadic - Fatal编程技术网

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...>>;