模板部分特化
有人知道根据什么规则下面的代码不能编译吗?
template <class T>
struct B
{
typedef T type;
};
template<class T>
struct X
{
};
template<class T>
struct X<B<T>::type*>//HERE I'M PARTIALLY SPECIALIZING (WELL, TRYING TO...)
{
};
请参阅代码内的注释。
Would any one knows according to what rules code below doesn't compile?
template <class T>
struct B
{
typedef T type;
};
template<class T>
struct X
{
};
template<class T>
struct X<B<T>::type*>//HERE I'M PARTIALLY SPECIALIZING (WELL, TRYING TO...)
{
};
Please see comment inside the code.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
你认为这会如何运作?编译器将查看某个地方是否有一个类 T 具有您的类的 typedef“类型”?
它只是不会。尽管它是一个指针。
请记住,您的 B 模板可能在某些地方是专门化的,因此该类型并不总是 T*,但它无法通过逆向工程推断出它。
对于那些不完全理解我的答案的人,您要求编译器做的是找到一个类 U,使得 B::type 是您作为参数传入的类。
很难确切地知道你为什么要尝试做你现在要做的事情。您可以对所有指针进行部分特化,然后对特定指针进行完全特化,这可以根据另一个模板来实现。
How do you think that will work? The compiler will look to see if there is a class T somewhere that has a typedef "type" to your class?
It just won't. Even though it's a pointer.
Remember that presumably your B template is presumably specialised in places so that type is not always T*, but it can't deduce it with reverse engineering.
For those who did not understand my answer fully, what you are asking the compiler to do is find a class U such that B::type is the class you pass in as a parameter.
It is difficult to know exactly why you are trying to do what you are. You can do a partial specialization on all pointers and then a total specialization on specific pointers, which could be implement in terms of another template.
您需要使用
typename
关键字,因为
B::type
是一个从属名称。所以typename
是必需的!--
编辑:
即使输入
typename
后,它也不会编译。我认为这是因为对于编译器来说,从X
中推导B
中的T
类型是很困难的,或者可能是不可能的。所以我相信它的非演绎上下文。请参阅此处的类似示例和讨论:
非推导中的模板参数部分特化中的上下文
但是,如果将特化更改为:
那么它就成为可推导的上下文,因此可以编译。
You need to use
typename
keyword as,It's because
B<T>::type
is a dependent name. Sotypename
is required!--
EDIT:
Even after putting
typename
, it isn't compiling. I think it's because deduction of typeT
inB<T>
fromX<U>
is difficult, or possibly impossible, for the compiler. So I believe its non-deduced context.See a similar example here and the discussion:
Template parameters in non-deduced contexts in partial specializations
However, if you change the specialization to this:
Then it becomes the deducible context, and so would compile.
假设您已经按照 Nawaz 的建议添加了
typename
。您遇到的错误消息中准确地解释了该问题:“模板参数在部分特化
B::type*
中不可推导。问题在于B:: type
和T
对于所有类型T
都完全相同:考虑以下示例:行
(*)
的结果是类型 MyClass2 本质上是MyClass1
因此,obj1
和obj2
应该是同一类的对象 现在,模板的版本。 >X
他们应该使用吗?如果您期望使用
X
的专用版本,请告诉我如果删除(*)
行,答案是否应该相同(显然obj2
也是如此)。仍然obj1
应该是X
的专门版本,如行(*)
。 。但现在我们希望编译器能够检测到某些类型可能被声明为 B::type,尽管我们从未这样做过 我们希望编译器验证所有可能的模板实例化,以检查其中之一是否没有奇怪的 typedef。
我希望这能澄清为什么编译器无法处理这种专业化。
可能有帮助的替代方案
我相信您的问题可以通过创建一个特征类来显式标记应该以特殊方式处理的类型来解决。像这样的事情:
另外,您可能会对 boost 库中的操作方式感兴趣,特别是 Boost.Type_Traits
Assuming you already added
typename
as suggested by Nawaz.The problem is exactly explained in the error message you encounter: "template parameter is not deducible in partial specialization
B<T>::type*
. The problem is thatB<T>::type
andT
is exactly the same for all typesT
. Consider the following example:The result of line
(*)
is a type MyClass2 which is essentiallyMyClass1
. So,obj1
andobj2
should be objects of the same class. Now, which version of templateX
should they use?If you would expect the specialised version of
X
, tell me if the answer should be the same if line(*)
is removed (and obviouslyobj2
as well). Stillobj1
should be the specialised version ofX
as line(*)
has nothing to do with it.But now we expect the compiler to detect that some type can be potentially declared as
B<T>::type
although we never do this. We expect the compiler to verify all possible template instantiations to check if there is no strange typedef in one of them.I hope this clarifies why such specialisation cannot be handled by the compiler.
An alternative that might help
I believe your problem could be attacked by creating a trait class for explicitly marking types that should be handled in a special way. Something like this:
Also, you might be interesting how it is done in boost library, in particular Boost.Type_Traits
“参数列表不能与非专用参数列表相同(它必须专门化某些东西)”
请参阅en.cppreference.com 上的partial_specialization
"The argument list cannot be identical to the non-specialized argument list (it must specialize something)"
see partial_specialization at en.cppreference.com