问题描述
以下代码几乎逐字地从David Abrahams& Co.的《 C ++模板元编程:Boost and Beyond的C ++模板元编程:概念,工具和技术》一书的第9.1.1节中复制而来。 Aleksey Gurtovoy。
The following code is copied almost verbatim from section 9.1.1 of the book C++ Template Metaprogramming: Concepts, Tools, and Techniques from Boost and Beyond by David Abrahams & Aleksey Gurtovoy.
唯一的变化是,我希望能够使用常规的Boost模板mpl :: identity从书中更改类型包装器模板。但是,在Microsoft Visual C ++ Express 2010(SP1)下,如果执行此操作,则会收到一个神秘的编译器警告。
The only change is that I want to be able to change the type wrapper template from the book with the regular Boost template mpl::identity. However, under Microsoft Visual C++ Express 2010 (SP1) I get a mysterious compiler warning if I do that.
似乎与类型包装器模板具有名为 type的内部typedef有关。将typedef更改为 Type(或简单地删除该行)将使代码正常工作。有人对这种怪异的行为有解释吗?
It seems somehow related to the fact that the type wrapper template has an inner typedef named "type". Changing that typedef to "Type" (or simply removing that line) will make the code work correctly. Does anyone have an explanation for this weird behavior?
#include <iostream>
#include <typeinfo>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/vector.hpp>
namespace mpl = boost::mpl;
// added a nested typedef named "type" is equivalent to mpl::identity
template <class T>
struct wrap
{
// changing type -> Type or removing this line
// makes the code compile and produce correct output!
typedef T type;
};
struct print_type
{
template <class T>
void operator() (wrap<T>) const
{
std::cout << typeid(T).name() << std::endl;
}
};
class A
{
A() {} // private constructor
};
class B
{
B() {} // private constructor
};
typedef boost::mpl::vector<A,B> AB;
int main()
{
boost::mpl::for_each<AB, wrap<mpl::_> >(
print_type()
);
/* Output:
class A
class B
*/
return 0;
}
/ I C:\Program的输出Files\boost\boost_1_47 / I C:\Program Files\boost / Zi / nologo / W3 / WX- / O2 / Oi / Oy- / GL / D WIN32 / D NDEBUG / D _CONSOLE / D _UNICODE / D UNICODE / Gm- / EHsc / GS / Gy / fp:precise / Zc:wchar_t / Zc:forScope /Fp\"Release\mpl.pch / Fa Release\ \ / Fo Release\ /Fd\"Release\vc100.pdb / Gd / analyze- / errorReport:queue
:
1>------ Build started: Project: mpl, Configuration: Release Win32 ------
1> main.cpp
1>C:\Program Files\boost\boost_1_47\boost/mpl/for_each.hpp(75): error C2784: 'void print_type::operator ()(wrap<T>) const' : could not deduce template argument for 'wrap<T>' from 'arg'
1> ..\..\..\mpl\main.cpp(20) : see declaration of 'print_type::operator ()'
1> C:\Program Files\boost\boost_1_47\boost/mpl/for_each.hpp(101) : see reference to function template instantiation 'void boost::mpl::aux::for_each_impl<false>::execute<first,last,TransformOp,F>(Iterator *,LastIterator *,TransformFunc *,F)' being compiled
1> with
1> [
1> TransformOp=wrap<boost::mpl::_>,
1> F=print_type,
1> Iterator=first,
1> LastIterator=last,
1> TransformFunc=wrap<boost::mpl::_>
1> ]
1> ..\..\..\mpl\main.cpp(42) : see reference to function template instantiation 'void boost::mpl::for_each<AB,wrap<T>,print_type>(F,Sequence *,TransformOp *)' being compiled
1> with
1> [
1> T=boost::mpl::_,
1> F=print_type,
1> Sequence=AB,
1> TransformOp=wrap<boost::mpl::_>
1> ]
========== Build: 0 succeeded, 1 failed, 2 up-to-date, 0 skipped ==========
推荐答案
某些术语,从:
- 元功能是具有嵌套类型的类型,该嵌套类型名为
type
- 元功能类是带有嵌套元函数的类型,该函数名为
apply
- 占位符表达式是一种类型要么是MPL占位符,要么是带有至少一个参数的类模板专业化,该参数本身就是一个占位符表达式
- A metafunction is a type with a nested type named
type
- A metafunction class is a type with a nested metafunction named
apply
- A placeholder expression is a type that is either an MPL placeholder or a class template specialization with at least one argument that itself is a placeholder expression
因此我们知道 wrap<>
是一个元函数,而 wrap< mpl :: _>
都是一个占位符表达式和一个元功能。
Thus we know that wrap<>
is a metafunction, and that wrap<mpl::_>
is both a placeholder expression and a metafunction.
当 mpl :: for_each<>
传递一个元功能或一个元功能 TransformOp
模板参数的tion类,它会评估该元函数/元函数类以获得转换结果。因此,如果您要通过原始占位符表达式而无需进一步评估,则占位符表达式必须不符合元函数或元函数类的条件。
When mpl::for_each<>
is passed a metafunction or a metafunction class for the TransformOp
template argument, it evaluates that metafunction/metafunction class to obtain the result of the transformation. Consequently, if you want to pass a raw placeholder expression without further evaluation, your placeholder expression must not meet the criteria of a metafunction or metafunction class.
在您的情况下,因为 wrap<>
是一个元函数,所以 mpl :: for_each<>
正在对其进行评估,并生成 A
和 B
作为转换类型;同时, print_type :: operator()<>
期望 wrap< A>
和 wrap< B>
-当然,这将拒绝编译。
In your scenario, because wrap<>
is a metafunction, mpl::for_each<>
is evaluating it and producing A
and B
as the transformed types; meanwhile, print_type::operator()<>
is expecting a wrap<A>
and wrap<B>
-- of course this will refuse to compile.
这篇关于带有boost :: mpl :: for_each的类型包装器错误(Abrahams& Gurtovoy书中的9.1.1节)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!