C++ 模板部分特化

C++ 模板部分特化,c++,templates,C++,Templates,有人知道下面的代码不编译的规则吗 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...) { }; 模板 结构B { T型; }; 模

有人知道下面的代码不编译的规则吗

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...)
{
};
模板
结构B
{
T型;
};
模板
结构X
{
};
模板
struct X//我在这里部分地进行了专门化(嗯,尝试…)
{
};

请参阅代码内的注释。

您需要使用
typename
关键字作为

template<class T>
struct X<typename B<T>::type*>
{
};

然后它就变成了可推断的上下文,编译也是如此

你认为这会怎样?编译器将查看是否有某个类T在您的类中具有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?
Foo类;
分类栏;
模板结构B
{
typedef int类型;
};
模板结构B
{
typedef int类型;
};
X//不明确,T是Foo还是Bar?

很难确切地知道你为什么要做你自己。您可以对所有指针进行部分专门化,然后对特定指针进行全部专门化,这可以通过另一个模板实现。

假设您已经按照Nawaz的建议添加了
typename

<>这个问题在您遇到的错误消息中得到了很好的解释:“模板参数在部分特化<代码> b::类型*< /代码>中不可推论。问题是<>代码> b::Type 和<代码> t>代码>对于所有类型<代码> t>代码>都是完全相同的。
class MyClass1 {};
typedef typename B<MyClass>::type MyClass2; //(*)

X<MyClass*> obj1;
X<MyClass2*> obj2;

另外,您可能会对boost库中的操作方式感兴趣,特别是我按照您的建议执行的Navaz,我得到了:错误1错误C2764:“T”:模板参数未使用或无法从VS中的部分专门化“X”中推断2010@There什么都不是。因为它不能。你试图做的超出了编译器的范围。@CashCow-wha你不是说超出了编译器的范围(请注意,我不是想和你或这里的任何人一起去,我只是想理解)@我们无能为力:请看我的编辑。还有指向讨论同一问题的好主题的链接!我认为它应该编译。它永远不应该与那种专门化相匹配。我真的不明白这个答案。编译器知道使用哪个类–
B
。每当
X
被实例化时,编译器绝对是c能够在
X
的所有部分专门化中搜索最具体的。事实上,它总是这样做。因此,纳瓦兹的答案是正确的。(续)或者更确切地说,我希望纳瓦兹的答案是正确的。显然它不起作用,但我无法理解编译器的抱怨(GCC的信息类似于VS 2010)。@Kondrad Nawaz的回答如果不编译就不可能是正确的,这就是我的想法。@Kondrad对你最后的评论说:这正是我所坚持的。根据哪个“子弹”“在std中,这不可编译?@Konrad和@There's nothing:我还想知道我的代码没有编译什么,尽管我觉得它是正确的。”问题是
B::type
t
对于所有类型
t
都是完全相同的-不。这不是问题(或者不应该是问题)。“现在,他们应该使用哪个版本的模板X?”–显然是专用版本,因为您的类型都是指针。这里使用
B::type
而不仅仅是
T
是完全不相关的。相关的是,专用化是一个指针。如果您希望所有指针都有专用版本,您应该有
X
,而不是
X
atter建议您只对某些指针进行专门化,而不是对所有指针进行专门化。这不是问题所在,而不是您有一个指针。如果您删除
*
“在这里使用B::type而不仅仅是T是完全不相关的”->它对编译器来说是相关且至关重要的。它不能推断出需要什么
B
来获得与当前类型的匹配,而当前类型是您想要实例化的。更糟糕的是,他甚至不知道在搜索匹配时他应该实际查看模板类B。为什么这是一个问题?为什么它不能推断出
B
?(事实上,没有推论,这是一个简单的替换)。假设您有1000个模板类,其中包含typedef。您认为编译器会检查所有模板类是否匹配?如果有多个匹配怎么办?
class MyClass1 {};
typedef typename B<MyClass>::type MyClass2; //(*)

X<MyClass*> obj1;
X<MyClass2*> obj2;
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> {};