微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c – 在实施类型列表时苦苦挣扎

出于教育目的,我想编写自己的基于c 11的类型列表.裸列表看起来像这样:
template <typename ... Ts> struct type_list;

template <typename T,typename ... Ts>
struct type_list<T,Ts ...> {
    typedef T Head;
    typedef type_list<Ts ...> Tail;
};

template <typename T> struct type_list<T> {
     typedef T Head;
     typedef null_type Tail;
};

我创建了一个名为front的函数提取一个元素:

template <typename T> struct front;

template <typename TypeList>
struct front {
    typedef typename TypeList::Head type;
};

哪个按预期工作,即此代码

typedef type_list<int> lst;
typedef type_list<float,int> lst2;
typedef type_list<double,float,int> lst3;
typedef type_list<char,double,int> lst4;

std::cout << "front(lst1): " << typeid( front<lst>::type ).name() << std::endl;
std::cout << "front(lst2): " << typeid( front<lst2>::type ).name() << std::endl;
std::cout << "front(lst3): " << typeid( front<lst3>::type ).name() << std::endl;
std::cout << "front(lst4): " << typeid( front<lst4>::type ).name() << std::endl;

生产:

front(lst1): i
front(lst2): f
front(lst3): d
front(lst4): c

当然,后退功能是下一步,但是,我似乎无法让它工作.我的代码

template <typename T> struct back;

template <typename TypeList>
struct back {
    typedef typename std::conditional<std::is_same<typename TypeList::Tail,null_type>::value,typename TypeList::Head,typename back<typename TypeList::Tail>::type>::type type;
};

不编译(clang 3.2)[lst定义为之前]:

TypeList.cc:33:71: error: no type named 'Tail' in 'null_type'
  typedef typename std::conditional<std::is_same<typename TypeList::Tail,~~~~~~~~~~~~~~~~~~~^~~~
TypeList.cc:35:20: note:
  in instantiation of template class 'back<null_type>' requested here
    typename back<typename TypeList::Tail>::type>::type type;
    ^

TypeList.cc:54:44: note:
  in instantiation of template class 'back<type_list<int> >' requested here
    std::cout << "back(lst1): " << typeid( back<lst>::type ).name() << std::endl;
                                           ^
1 error generated.

>为什么std :: conditional不会触发?

解决方法

std :: conditional的使用不当
std::conditonal<condition,true-type,false-type>

你的问题归结为std :: conditional中的true和false类型都必须产生一个有效的名字,无论条件选择哪一方.

注意:如果不需要完整的解释,本文末尾有一个建议的解决方案.

考虑以下示例:

struct A { typedef int type; };
struct B { /* empty */ };
template<class T>
struct some_trait {
  typedef typename std::conditional<
    /*  condition -> */ std::is_same<T,A>::value,/*  true-type -> */ typename T::type,/* false-type -> */ void
  >::type result;
};

实例化some_trait< A>将完全有效,但如果我们用B实例化会发生什么?

template<>
struct some_trait<B> {
  typedef typename std::conditional<
    std::is_same<B,typename B::type,// (A),ill-formed
    void
  >::type result;
};

在上面我们假装是一个编译器,并且我们用B替换了每个T的出现,但这并不是那么辛苦,但它已经在我们的主模板中引发了一个非常重要的问题.

当编译器实例化some_trait< T>时如果T = B,我们的std :: conditional中的true类型将是B :: type(A).

但是由于B里面没有名字叫做类型,我们会得到一个编译器诊断说我们的代码有问题,即;我们正在尝试访问不存在的名称.

foo.cpp:15:37: error: no type named 'type' in 'B'
    /*  true-type -> */ typename T::type,ill-formed

提出的解决方

毫无疑问,我们必须做些什么,并简而言之;阻止我们的模板访问可能不存在的名称.

这样做的一个简单方法是依赖显式特化,而不是使用std :: conditional.

后面的示例实现

template<typename TypeList>
struct back {
  typedef typename back<typename TypeList::Tail>::type type;
};

template<typename T>
struct back<type_list<T>> {
  typedef typename type_list<T>::Head type;
};

注意:如果模板的实例化< typename T>结构;是一个只有一个参数的type_list,我们知道我们在最后一个节点.

原文地址:https://www.jb51.cc/c/110496.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐