根据下面的规则,任何人都知道不编译吗?
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...)
{
};
请参阅代码内的评论。
答案 0 :(得分:9)
您认为这会如何运作?编译器会查看某个类的某个类是否有类型为typedef“type”的类?
它不会。即使它是一个指针。
请记住,大概你的B模板可能在某些地方是专用的,因此类型并不总是T *,但它不能通过逆向工程来推断它。
对于那些完全不理解我的答案的人,你要求编译器做的是找到一个类U,这样B :: type就是你作为参数传入的类。
class Foo;
class Bar;
template<> struct B<Foo>
{
typedef int type;
};
template<> struct B<Bar>
{
typedef int type;
};
X<int*> // ambiguous, T is Foo or Bar?
很难确切地知道你为什么要做你想做的事。你可以对所有指针进行部分特化,然后对特定指针进行全面的特化,这可以用另一个模板来实现。
答案 1 :(得分:4)
您需要使用typename
关键字作为
template<class T>
struct X<typename B<T>::type*>
{
};
这是因为B<T>::type
是一个从属名称。所以typename
是必需的!
-
编辑:
即使在放置typename
之后,它也没有编译。我认为这是因为从T
B<T>
中删除X<U>
类型对于编译器来说很难或者可能是不可能的。所以我相信它的非推断背景。
在此处查看类似示例和讨论:
Template parameters in non-deduced contexts in partial specializations
但是,如果您将专业化更改为:
template<class T>
struct X<B<T> >
{
};
然后它成为可推导的上下文,因此编译。
答案 2 :(得分:0)
假设您已根据Nawaz的建议添加了typename
。
问题在您遇到的错误消息中得到了解释:“模板参数在部分特化B<T>::type*
中无法推导。问题是B<T>::type
和T
完全相同所有类型T
。请考虑以下示例:
class MyClass1 {};
typedef typename B<MyClass>::type MyClass2; //(*)
X<MyClass*> obj1;
X<MyClass2*> obj2;
行(*)
的结果是MyClass2类型,它本质上是MyClass1
。因此,obj1
和obj2
应该是同一个类的对象。现在,他们应该使用哪个版本的模板X
?
如果你期望X
的专业版,请告诉我,如果删除了行(*)
,答案应该是相同的(显然obj2
也是如此)。仍然obj1
应该是X
的专用版本,因为行(*)
与它无关。
但是现在我们希望编译器检测到某些类型可能被声明为B<T>::type
,尽管我们从未这样做过。我们希望编译器验证所有可能的模板实例,以检查其中一个是否存在奇怪的typedef。
我希望这可以澄清为什么编译器无法处理这种专业化。
可能有帮助的替代方案
我相信你的问题可能会受到攻击,因为它创建了一个特性类来明确标记应该以特殊方式处理的类型。像这样:
template <bool v>
struct boolean_value {
static const bool value=v;
};
template <typename T>
struct is_my_interesting_type : public boolean_value<false> {};
class MyClass {
...
};
template <>
struct is_my_interesting_type<MyClass> : public boolean_value<true> {};
template <typename T, bool special>
class InternalX {
... //generic version of your template X
};
template <typename T>
class InternalX<T,true> {
... //special version of your template X
};
template <typename T>
class X : public InternalX<T,is_my_interesting_type<T>::value> {};
此外,您可能会对如何在boost库中完成它感兴趣,特别是Boost.Type_Traits