努力与类型列表的实现 [英] Struggling with implementation of a type list

查看:128
本文介绍了努力与类型列表的实现的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

出于教育目的,我想编写我自己的 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 ...>尾巴;
};

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

我创建了一个 front 提取第一个元素:

  template< typename T&结构体

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

它的工作原理如下:



< pre class =lang-c ++ prettyprint-override> typedef type_list< int> lst;
typedef type_list< float,int> lst2;
typedef type_list< double,float,int> lst3;
typedef type_list< char,double,float,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:在'null_type'中没有名为'Tail'的类型
typedef typename std :: conditional< std :: is_same< typename TypeList :: Tail,null_type> :: value,
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ back< null_type>'请求这里
typename返回< typename TypeList :: Tail> :: type> :: type type;
^

TypeList.cc:54:44:note:
在实例化模板类'back< type_list< int> >'requested here
std :: cout<< back(lst1):< typeid(back< lst> :: type).name()<< std :: endl;
^
生成了1个错误。






问题




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


解决方案

std :: conditional

的不当使用

  std :: conditionalonal< condition,true-type,false-type> 

您的问题归结为 true - 无论条件选择哪一侧, std :: conditional 都必须产生有效的名称。



注意:如果不需要完整说明,在此帖子末尾有一个建议的解决方案






请考虑以下示例:

  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 ?实例化它会发生什么?

 模板<> 
struct some_trait< B> {
typedef typename std :: conditional<
std :: is_same< B,A> :: value,
typename B :: type,//(A),ill-formed
void
>结果;
};

在上面我们假装是一个编译器,我们替换每一次出现的 T B ,这不是所有的努力工作,但它提出了一个非常重要的问题,我们的主模板<当编译器使用 T = B

来实例化 some_trait< T> / code>,我们的 std :: conditional 中的 true类型将是 B :: type



但由于 B 名称里面调用类型,我们将得到一个编译器诊断说我们的代码有问题,即;我们正在尝试访问不存在的名称。

  foo.cpp:15: 37:错误:在'B'中没有名为'type'的类型
/ * true-type - > * / typename T :: type,//(A),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;
};

注意:如果实例化 template< typename T> struct back; 是只有一个参数的 type_list ,我们知道我们在最后一个节点。


For educational purposes I want to write my own c++11 based typelist. The bare list looks like this:

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

I have created a function called front for extracting the first element:

template <typename T> struct front;

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

Which works as expected, i.e. this code

typedef type_list<int> lst;
typedef type_list<float,int> lst2;
typedef type_list<double,float,int> lst3;
typedef type_list<char,double,float,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;

produces:

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

Naturally, a back function is the next step, however, I can't seem to get it to work. My code

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

does not compile (clang 3.2) [lst is defined as before]:

TypeList.cc:33:71: error: no type named 'Tail' in 'null_type'
  typedef typename std::conditional<std::is_same<typename TypeList::Tail, null_type>::value,
                                                 ~~~~~~~~~~~~~~~~~~~^~~~
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.


Question

  • Why does the std::conditional not trigger?

解决方案

Improper usage of std::conditional

std::conditonal<condition, true-type, false-type>

Your problem boils down to that both the true- and false-type in std::conditional must yield a valid name, no matter which side the condition picks.

Note: There's a proposed solution at the end of this post if a full explanation isn't needed.


Consider the below example:

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


Instantiating some_trait<A> will be perfectly valid, but what happens if we instantiate it with B?

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

In the above we are pretending to be a compiler, and we replaced every occurance of T with B, it's not all that hard work but it has raised a very important issue with our primary-template.

When the compiler instantiates some_trait<T> with T = B, the true-type in our std::conditional will be B::type (A).

But since B has no name inside it called type we will get a compiler diagnostic saying that there's something wrong with our code, namely; we are trying to access a name which doesn't exist.

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



Proposed Solution

There really is no doubt to what we have to do, and to put it in short; prevent our template from accessing names that potentially doesn't exist.

A simple way of doing this is to rely on explicit specialization, instead of using a std::conditional.


Sample implementation of back

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

Note: If the instantiation of template<typename T> struct back; is a type_list with only one parameter, we know we are at the last node.

这篇关于努力与类型列表的实现的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆