【问题标题】:syntax help required on templated static member function模板化静态成员函数所需的语法帮助
【发布时间】:2010-03-23 02:22:06
【问题描述】:

我有一堆对象指针容器,我想在不同的上下文中对其进行迭代,以便为它们生成诊断信息。我正在为定义函数所需的语法而苦苦挣扎……由于这些对象通过我的应用程序的不同部分进行过滤,因此最好将其封装在一个专用的诊断类中:

// Code sketch only - detail fleshed out below...  
class ObjectListDiagnoser  
{  
public:  
    static void GenerateDiagnostics( /* help required here! */ );  
};  

...

// Elsewhere in the system...  
ObjectListDiagnoser::GenerateDiagnostics( /* help required here! */ );  

我希望能够做的(在我的应用程序中的某些地方)至少是这样的:

std::vector<MyObject *> objGroup1;  
std::list<MyObject *> objGroup2;

ObjectListDiagnoser::GenerateDiagnostics( objGroup1.begin(), objGroup1.end() );  
ObjectListDiagnoser::GenerateDiagnostics( objGroup2.begin(), objGroup2.end() );  
ObjectListDiagnoser::GenerateDiagnostics( objGroup1.rbegin(), objGroup1.rend() );  

我尝试以两种方式对我的函数进行模板化,但均未成功:

class ObjectListDiagnoser  
{  
public:  
    // 1 - nope.  
    template <class ObjIter>
    static void GenerateDiagnostics( ObjIter first, ObjIter last );  
    // 2. - nope.  
    template <class Container, class ObjIter>
    static void GenerateDiagnostics( Container<MyObject *>::ObjIter first,  
                                     Container<MyObject *>::ObjIter last );  
};  

有人可以为此提供正确的语法吗?容器类型会有所不同,迭代的方向也会有所不同,但总是针对相同类型的对象。


以下 cmets 中的讨论摘要 - 案例 1 是正确的...但如果模板函数定义不在标头中,则会导致广泛无法理解的链接器错误。模板函数定义只需放在标题中 - 很容易忘记这一点。将其滑入标题中,一切都很好 - 编译、链接……甚至可以运行。

【问题讨论】:

  • 案例 1 有什么问题?据我所知,这应该没问题。
  • 旁注:在 C++ 中,不需要类来分组函数,而是使用命名空间。
  • @gf:该对象可能有用地保存诸如流或格式首选项之类的东西。
  • 写错了,"如果你只想对函数进行分组"
  • @sth - sase 1 导致我出现链接器错误。看来我调用函数的方式不足以让编译器将函数与其拥有的模板匹配。我可以将不可编译的代码放入函数定义的主体中,并且它永远不会引发编译器错误......也许我需要按照下面的 Yogesh 在某处输入一个或两个“类型名”? @gf - 我正在分组为一个类进行格式化,正如 Potatoswatter 猜测的那样。

标签: c++ templates iterator


【解决方案1】:

您应该使用选项 1。与 &lt;algorithm&gt; 中的函数一样,容器类型不属于模板参数。

我们需要更多关于出了什么问题的信息。你应该没问题……你只需要添加定义。

template <class ObjIter>
static void ObjectListDiagnoser::GenerateDiagnostics
 ( ObjIter first, ObjIter last ) {
   …
}

编辑: 与所有模板一样,此定义需要放在头文件中。广泛不支持在定义模板的源文件之外使用模板。

您可以使用显式实例化,它允许在非头文件中实现,但否定了使用模板的一些好处:您只能使用显式实例化的模板参数。

// implementation in source file

template <class ObjIter>
static void ObjectListDiagnoser::GenerateDiagnostics
 ( ObjIter first, ObjIter last ) {
   …
}

template void ObjectListDiagnoser::GenerateDiagnostics
  < std::list<Object>::iterator >
 ( std::list<Object>::iterator first, std::list<Object>::iterator last );

template void ObjectListDiagnoser::GenerateDiagnostics
  < std::vector<Object>::iterator >
 ( std::vector<Object>::iterator first, std::vector<Object>::iterator last );

// now you can only use vector<Object>::iterator or list<Object>::iterator
// as arguments.

【讨论】:

  • 根据对我的问题的评论...这会导致我出现链接器错误。错误开始于:error LNK2019: unresolved external symbol "public: static void __cdecl ObjectListDiagnoser::GenerateDiagnostics >: :_Iterator > >(class std::reverse_iterator >::_Iterator, ... 并继续比我在此评论中的空间更多!
  • 注意 - 当我在第二种情况下调用我的函数时发生上述链接错误(通过 std::list 前向传递)。我还没有尝试过 std::vector 或 reverse_iterator 案例......
  • 道歉 - 我从我的代码中提取了这个简化版本,其中有两个函数。第二个函数用于格式化,它通过列表估计诊断显示所需的大小。上面的链接错误是针对实际诊断的,它确实通过 std::list 向后运行。这两个函数都会产生链接错误。前向传递函数产生如下错误...
  • error LNK2019: unresolved external symbol "public: static class CSize __cdecl ObjectListDiagnoser::GetDiagnosticDisplaySize >::_Iterator >(class std::list >::_Iterator,class std::list >::_Iterator,int)"
  • @omatai:我更新了我的答案。我怀疑您正在尝试在一个 .cpp 文件中定义函数模板并在另一个文件中使用它。
【解决方案2】:

我同意@sth,1 没有问题。事实上,这就是 STL 算法的声明方式参考 - find

如果 1 有效,则不需要 2。它的声明应该是任何方式

template <class Container>
static void GenerateDiagnostics( typename Container<MyObject *>::iterator first, 
       typename Container<MyObject *>::iterator last );  

请注意 - 这只是一个适用于容器的iterator 的示例,可能不适用于其reverse_iteratorconst_iterator

【讨论】:

  • 不,这不是它应该的样子。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-20
  • 2013-05-30
  • 1970-01-01
相关资源
最近更新 更多