遍历 boost::mpl::list 的惯用方法是什么?
编辑:我已经编辑了示例以更好地类似于我遇到的问题,现在该函数依赖于常规参数(而不仅仅是模板参数),这意味着计算不能 在编译时进行。
我用手写了一些代码 typelist 现在我们开始使用 boost 我正在尝试将其移至 mpl
库。
我似乎找不到任何像样的 mpl::list 文档,甚至无法将代码移植到 boost::mpl 。 我有一种感觉,即使(如果?)我确实成功移植了代码,它仍然不符合习惯。 您能否让我知道如何使用 boost
编写以下内容(请注意,这不是实际的代码,而是人为的简化)。
原始代码 (codepad.org粘贴)
class nil {};
template <class Head, class Tail = nil>
struct type_list {
typedef Head head;
typedef Tail tail;
};
template <class List>
struct foo;
template <class Head, class Tail>
struct foo<type_list<Head, Tail> >{
template <class T>
static void* bar(T* obj, size_t size)
{
if (sizeof(Head) == size)
return reinterpret_cast<Head*>(obj);
// Otherwise check the rest of the list
return foo<Tail>::bar(obj, size);
}
};
template <>
struct foo<nil>
{
template <class T>
static void* bar(T*, size_t) { return NULL; }
};
#include <iostream>
int main()
{
int n = 3;
void *p = foo<type_list<char, type_list<bool,
type_list<double, type_list<long> > > >
>::bar(&n, 4);
std::cout<< p << std::endl;
}
尝试使用Boost失败< /strong> (codepad.org 粘贴)
#include <boost/mpl/list.hpp>
template <class List>
struct foo{
template <class T>
static void* bar(T* obj, size_t size)
{
typedef typename boost::mpl::front<List>::type type;
if (sizeof(type) == size)
return reinterpret_cast<type*>(obj);
// Otherwise check the rest of the list
return foo<typename List::next>::bar(obj, size);
}
};
template <>
struct foo<boost::mpl::list0<boost::mpl::na> >
{
template <class T>
static void* bar(T*)
{
return NULL;
}
};
#include <iostream>
int main()
{
int n = 3;
void *p = foo<boost::mpl::list<char, bool, double, long> >::bar(&n, 4);
std::cout << p << std::endl;
}
Edit: I've edited the sample to better resemble the problem I have, now the function depends on a regular parameter (and not only on template parameters) which means that the computations can't be made at compile time.
I wrote some code with a hand written typelist and now we've started using boost and I'm trying to move it to the mpl
library.
I can't seem to find any decent documentation for mpl::list
and I'm even failing to port the code to boost::mpl
. I've got the feeling that even when (if?) I do succeed in porting the code it will still not be idiomatic. Can' you please let me know how the following should be written with boost
(note that this is not the actual code, it's a contrived simplification).
Original code (codepad.org paste)
class nil {};
template <class Head, class Tail = nil>
struct type_list {
typedef Head head;
typedef Tail tail;
};
template <class List>
struct foo;
template <class Head, class Tail>
struct foo<type_list<Head, Tail> >{
template <class T>
static void* bar(T* obj, size_t size)
{
if (sizeof(Head) == size)
return reinterpret_cast<Head*>(obj);
// Otherwise check the rest of the list
return foo<Tail>::bar(obj, size);
}
};
template <>
struct foo<nil>
{
template <class T>
static void* bar(T*, size_t) { return NULL; }
};
#include <iostream>
int main()
{
int n = 3;
void *p = foo<type_list<char, type_list<bool,
type_list<double, type_list<long> > > >
>::bar(&n, 4);
std::cout<< p << std::endl;
}
Failed Attempt to use Boost (codepad.org paste)
#include <boost/mpl/list.hpp>
template <class List>
struct foo{
template <class T>
static void* bar(T* obj, size_t size)
{
typedef typename boost::mpl::front<List>::type type;
if (sizeof(type) == size)
return reinterpret_cast<type*>(obj);
// Otherwise check the rest of the list
return foo<typename List::next>::bar(obj, size);
}
};
template <>
struct foo<boost::mpl::list0<boost::mpl::na> >
{
template <class T>
static void* bar(T*)
{
return NULL;
}
};
#include <iostream>
int main()
{
int n = 3;
void *p = foo<boost::mpl::list<char, bool, double, long> >::bar(&n, 4);
std::cout << p << std::endl;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
警告:有一段时间没有做过任何 C++(与此相关的元编程),所以我可能是错的。
如果我理解正确,您的原始代码会找到第一个类型,它的大小与传递的参数相同,并将参数转换为该类型。 假设,使用
mpl
实现它基本上可以归结为使用 find_if 算法,带有自定义书面谓词来测试类型大小(请参阅上面链接中的示例)。 只需typedef
结果,转换它就完成了。Warning: haven't done any C++ (meta programming for that matter) in a while, so I might be wrong.
If I understand correctly, your original code finds the first type, which has the same size as does the passed argument and casts the argument to that type. Assuming that, implementing it with
mpl
would basically boil down to using the find_if algorithm with a custom written predicate to test for type size (see the example in the link above). Justtypedef
the result, cast it and you're done.如果我理解正确的话,您在运行时传递一个 T 并希望您的 {A, B, C, D} 的 MPL 列表将选择该集合中的正确 T 并对其执行操作?
我可能是错的,但这听起来像是适合 Boost.Fusion 的东西,它是为编译时序列的运行时迭代而设计的。
If I understand correctly, you're passing in a T at runtime and hoping that your MPL list of {A, B, C, D} will select and act upon the correct T in that set?
I may be wrong, but this sounds like something suited to Boost.Fusion, which is designed for runtime iteration of compile-time sequences.
MPL 不适合混合编译时/运行时操作。
MPL 序列运行时允许的唯一操作是“for_each”。 对于所有其他情况,您应该自己解决。
因此,您应该有效地考虑 MPL 类型并不意味着被实例化。
然而,Boost 中还有其他功能可以实现这样的功能。
旧的:Boost.Tuple
新的:Boost.Fusion > http://spirit.sourceforge.net/dl_more/ fusion_v2/libs/fusion/doc/html/index.html
Boost.Fusion 有点复杂(例如,它集成了视图的概念),但更适合您的示例。
这并不意味着您不应该使用 MPL。 相反,Boost.Fusion参考文档中明确指出,应该使用MPL算法进行编译时计算,然后仅在跨越编译时/运行时边界的那一刻构建Boost.Fusion容器(甚至尽管 Boost.Fusion 容器应该与 MPL 算法一起工作)。
因此,请保持 mpl 实现将结果列表转换为 Boost.Fusion 序列。
然后实例化该序列并使用所有 Boost.Fusion 设施。
The MPL is ill-suited for mixed compile-time / run-time operations.
The only operation allowed at runtime on MPL sequences is 'for_each'. For all other situations you should roll your own.
So you should effectively consider that MPL types are not meant to be instanciated.
However, there are other facilities in Boost for such a thing.
The old: Boost.Tuple
The new: Boost.Fusion > http://spirit.sourceforge.net/dl_more/fusion_v2/libs/fusion/doc/html/index.html
Boost.Fusion is a bit more complex (it integrates the concept of views, for example), but would be far better suited to your example.
It does not mean that you should not use the MPL. On the contrary, it is explicitly stated in the Boost.Fusion reference document that one should use MPL algorithms for compile-time computations, and then build the Boost.Fusion container only at the moment you cross the compile-time / runtime boundary (even though Boost.Fusion container are supposed to work with MPL algorithms).
So, keep your mpl implementation transform the resulting list to a Boost.Fusion sequence.
Then instantiate the sequence and make use of all the Boost.Fusion facilities.
使用
boost::mpl::像这样折叠
:在这里打印
0
,但是我在amd64上,所以我需要将4
更改为8
,并得到非零值。华泰
Use
boost::mpl::fold
like this:Prints
0
here, but then I'm on amd64, so I need to change the4
to an8
, and get something non-zero.HTH