C++ 中非模板类的专门成员函数

发布于 2024-11-08 22:26:12 字数 943 浏览 9 评论 0原文

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

#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 不会被调用。我怎样才能做到这一点?

I'm trying to specialize a template member function of a non-template class using a templatized parameter:

#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
}

I get an error "illegal use of explicit template arguments" with this. What's the right syntax to make this valid?


Update:

Perhaps I've muddled the issue by over-simplifying. What I really want to do is specially handle this one case where there is a dependent name involved, which I think may be what is throwing a monkey wrench into the works here. My original thought was to overload the function as such:

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"!
}

But the special Foo doesn't get called. How can I do that?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

維他命╮ 2024-11-15 22:26:12

只有成员函数是模板化的,这意味着您只能在其中使用一个 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() );
}

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

Only the member function is templated, which means that you should only use one template<...> in there. But that will not solve it either, as you cannot partially specialize a function.

The usual way of handling the problem is through overloads, rather than specialization (specialization of template functions is not that useful).

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

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

Note that the difference is that they are two separate template functions (rather than an specialization).

EDIT: After the update

The update to the question changes the problem completely. The problem that you are seeing is that the argument of the second version is a dependent name, and as such it is non deducible. Given the function call the compiler is not able to determine what type T, and integral constant N are to match that particular instantiation. Consider a different example:

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() );
}

When the compiler processes the call in main, it instantiates the template and extracts the type, from that it creates a temporary, and then it tries to decide what to do with foo but at that time it only knows that it is being called with an int rvalue... the original inner<double>::type is gone, now it is just foo( int() ) and the compiler would have to try and instantiate inner_int with all possible types to determine whether any of them fits, and in the worse case, as above, many would match.

极致的悲 2024-11-15 22:26:12

部分函数模板特化是非法的。来自 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::iterator 只是 T*,您的“特殊”重载可以是:

template<typename T>
void Foo(T*&)
{
    // special
}

Partial function template specialization is illegal. From the C++03 standard, §14/2:

A template-declaration can appear only as a namespace scope or class scope declaration. In a function template declaration, the declarator-id shall be a template-name (i.e., not a template-id). [Note: in a class template declaration, if the class name is a template-id, the declaration declares a class template partial specialization.]

You'll want to simply overload your function instead:

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

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

EDIT (in response to the OP's edit):

If you're only looking for a workaround for this specific scenario, since std(::tr1)::array<T,N>::iterator is simply T*, your 'special' overload can be:

template<typename T>
void Foo(T*&)
{
    // special
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文