4

我正在尝试使用模板化参数专门化非模板类的模板成员函数:

#include <array>
class C
{
public:
  template<class Container>
  void Foo( Container& )
  {
    // ...
  }
};

template<class T, std::size_t N>
template<>
void C::Foo< std::tr1::array<T,N> >( std::tr1::array<T,N>& )
{
  // special
}

我收到一个错误“非法使用显式模板参数”。使此有效的正确语法是什么?


更新

也许我过度简化了这个问题。我真正想做的是专门处理这种涉及依赖名称的情况,我认为这可能是在这里投入活动的原因。我最初的想法是像这样重载函数:

class C
{
public:
  template<class Iter>
  void Foo( Iter )
  {
    std::cout << "Normal\n";
  }

  template<class T, std::size_t N>
  void Foo( typename std::tr1::array<T,N>::iterator )
  {
    std::cout << "Special\n";
  }
};

int main()
{
  C c;
  std::tr1::array<int,10> a1;
  c.Foo( a1.begin() ); // Doesn't print "Special"!
}

但是特殊的 Foo 没有被调用。我怎样才能做到这一点?

4

2 回答 2

2

只有成员函数是模板化的,这意味着您应该只template<...>在其中使用一个。但这也不能解决它,因为你不能部分专门化一个函数。

处理问题的常用方法是通过重载,而不是专门化(模板函数的专门化没有那么有用)。

struct test {
   template <typename Container>
   void f( Container& ) { ... }

   template <typename T, int N>
   void f( std::array<T,N>& ) { ... }
};

请注意,不同之处在于它们是两个独立的模板函数(而不是专门化)。

编辑:更新后

问题的更新完全改变了问题。您看到的问题是第二个版本的参数是一个从属名称,因此它是不可演绎的。给定函数调用,编译器无法确定什么类型 T 和整数常量 N 来匹配那个特定的实例化。考虑一个不同的例子:

template <typename T>
struct inner_int {
   typedef int type;
};
template <typename T>
void foo( typename inner_int<T>::type ) {
}
int main() {
   foo( inner_int<double>::type() );
}

当编译器处理 in 中的调用时main,它会实例化模板并提取类型,从中创建一个临时的,然后尝试决定如何处理,foo但那时它只知道它是用int右值调用的。 ..原来inner<double>::type的已经消失了,现在它只是foo( int() ),编译器将不得不尝试inner_int使用所有可能的类型进行实例化,以确定它们中的任何一个是否适合,并且在更坏的情况下,如上所述,许多会匹配。

于 2011-05-20T19:58:01.690 回答
1

部分函数模板特化是非法的。来自 C++03 标准,§14/2:

模板声明只能作为命名空间范围或类范围声明出现。在函数模板声明中,declarator-id应为模板名称 (即,不是模板 ID。[注意:在类模板声明中,如果类名是template-id,则声明声明类模板部分特化。]

你会想要简单地重载你的函数:

class C
{
public:
    template<typename Container>
    void Foo(Container&)
    {
        // ...
    }

    template<typename T, std::size_t N>
    void Foo(std::tr1::array<T, N>&)
    {
        // special
    }
};

编辑(响应 OP 的编辑):

如果您只是为这种特定情况寻找解决方法,因为std(::tr1)::array<T,N>::iteratoris simple T*,您的“特殊”重载可以是:

template<typename T>
void Foo(T*&)
{
    // special
}
于 2011-05-20T20:00:38.480 回答