模板类型列表中的递归解除引用,如何返回正确的类型

时间:2016-08-30 19:32:29

标签: c++ templates template-meta-programming

我是模板元编程的新手,并尝试在Nicolas Brailovsky博客的帮助下完成第一步。

我创建了以下场景:

TEST(Check_NthInstance)
{
    typedef Lst< char, Lst< int>> a;  // a list of types
    Instances<a> inst; //Holds an instance value for each type

    char&   ref1 = NthInstance<a, 0>::get(inst);    
    ref1 = 'x'; //can easily manipulate an instance depending on the type

    int& ref2 = NthInstance<a, 1>::get(inst); //here we get a compile error
}

在这个场景中,我试图在

中获得对实例值的引用
Instances<a> inst;

按索引。

所需的声明如下:

struct NIL 
{
    typedef NIL Head;
    typedef NIL Tail;
};

template <typename H, typename T=NIL> struct Lst 
{
    typedef H Head;
    typedef T Tail;
};

template <typename LST> struct Instances 
{
    typedef typename LST::Head Elm;
    Elm instance;
    Instances<typename LST::Tail> next;
};
template <> struct Instances<NIL> {};

template <typename TypeLst, int N> struct NthInstance 
{
    typedef typename TypeLst::Tail TypeNext;
    typedef typename NthInstance<TypeLst, N-1>::NthInstanceType NthInstanceType;

    template <typename InstancesLst> 
    static NthInstanceType& get(InstancesLst &instances_lst) 
    {
        return NthInstance::get(instances_lst.next);
    }
};

template <typename TypeLst> struct NthInstance<TypeLst, 0> 
{
    typedef typename TypeLst::Head NthInstanceType;

    template <typename InstancesLst>
    static NthInstanceType& get(InstancesLst &instances_lst) 
    {
        return instances_lst.instance;
    }
};

我想,问题是这一行中的递归演绎:

return NthInstance::get(instances_lst.next);

编译器消息(VS2010)实际上没有帮助:

1>...\empty.cpp(59): error C2440: 'initializing' : cannot convert from 'char' to 'int &'

我还发现,我的类型解引用没有按预期工作:

NthInstance<a,0>::NthInstanceType

应与

不同
NthInstance<a,1>::NthInstanceType

问题是,如何正确编写?

如果可能,请提供非c ++ 11示例。

2 个答案:

答案 0 :(得分:1)

你可能想做这样的事情:

#include <iostream>

struct Nil { };

template <class Type, class Next = Nil>
struct Lst {
   typedef Type ValueType;
   typedef Next NextType;
   Type value;
   Next next;
};

template <int N, class L>
struct GetterType:GetterType<N-1, typename L::NextType> { };

template <class L>
struct GetterType<0, L> {
   typedef typename L::ValueType ValueType;
};

template <int I>
struct Getter {
   template <class L>
   static typename GetterType<I, L>::ValueType& get(L &lst) {
      return Getter<I-1>::get(lst.next);
   }
};

template <>
struct Getter<0> {
   template <class L>
   static typename GetterType<0, L>::ValueType& get(L &lst) {
      return lst.value;
   }
};

int main() {
   Lst<char, Lst<int> > lst;
   Getter<1>::get(lst) = 10;
   Getter<0>::get(lst) = 'a';
   std::cout << Getter<0>::get(lst) << std::endl;
   std::cout << Getter<1>::get(lst) << std::endl;
}

答案 1 :(得分:0)

你确定这条线是正确的吗?

typedef Lst< char, Lst< int>> a;  // a list of types

在预C ++ 11中它应该是

typedef Lst<char, Lst<int> > a;  // a list of types