ele*_*kil 6 c++ templates metaprogramming template-meta-programming c++11
出于教育目的,我想写自己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;
};
Run Code Online (Sandbox Code Playgroud)
我创建了一个调用front
提取第一个元素的函数:
template <typename T> struct front;
template <typename TypeList>
struct front {
typedef typename TypeList::Head type;
};
Run Code Online (Sandbox Code Playgroud)
哪个按预期工作,即此代码
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;
Run Code Online (Sandbox Code Playgroud)
生产:
front(lst1):i
front(lst2):f
front(lst3):d
front(lst4):c
当然,back
功能是下一步,但是,我似乎无法让它工作.我的代码
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;
};
Run Code Online (Sandbox Code Playgroud)
不编译(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, 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.
Run Code Online (Sandbox Code Playgroud)
std::conditional
触发?std::conditional
std::conditonal<condition, true-type, false-type>
Run Code Online (Sandbox Code Playgroud)
你的问题可以归结为,无论是道道通和假型中std::conditional
必须产生一个有效的名称,无论哪一方面的条件选秀权.
注意:如果不需要完整的解释,本文末尾有一个建议的解决方案.
考虑以下示例:
struct A { typedef int type; };
struct B { /* empty */ };
Run Code Online (Sandbox Code Playgroud)
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;
};
Run Code Online (Sandbox Code Playgroud)
实例化some_trait<A>
将是完全有效的,但是如果我们实例化它会发生什么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;
};
Run Code Online (Sandbox Code Playgroud)
在上面的,我们假装是一个编译器,我们更换的每一次出现T
用B
,这不是所有的辛苦工作,但它已经提出了与我们的一个非常重要的问题主要模板.
当编译器实例some_trait<T>
用T = B
的真型在我们的std::conditional
将是B::type
(A) .
但由于B
内部没有名称,type
我们将得到一个编译诊断程序,说我们的代码有问题,即; 我们正在尝试访问不存在的名称.
foo.cpp:15:37: error: no type named 'type' in 'B'
/* true-type -> */ typename T::type, // (A), ill-formed
Run Code Online (Sandbox Code Playgroud)
毫无疑问,我们必须做些什么,并简而言之; 阻止我们的模板访问可能不存在的名称.
这样做的一个简单方法是依赖显式特化,而不是使用std::conditional
.
示例实现 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;
};
Run Code Online (Sandbox Code Playgroud)
注意:如果的实例template<typename T> struct back;
是type_list
,只有一个参数,我们知道我们是在最后一个节点.
归档时间: |
|
查看次数: |
744 次 |
最近记录: |