【问题标题】:explicit instantiation of parameterized template methods参数化模板方法的显式实例化
【发布时间】:2010-11-16 21:26:03
【问题描述】:

我有两个不同的模板类,其中一个使用另一个模板类的对象作为参数。我收到一条错误消息: collect2: ld 返回 1 个退出状态 make: * [main] 错误 1

我正在处理模板的显式实例化,我发现了一些相关的帖子,但它们大多与单个模板类的实例化有关。就我而言,每个类有 3 个文件(.h、.cpp、.inc 遵循http://www.parashift.com/c++-faq/templates.html#faq-35.13 的建议)。

foo.h

 #ifndef FOO_H
 #define FOO_H
 template < class S >
 class Foo{
    public: ...
    private: ... 
 };
 #endif

foo.cpp

  ...
  template < class S >
  Foo<S>::Foo(){ .... }
  ...
  #include "foo.inc"

foo.inc

 template class Foo<int>;
 template class Foo<float>;

bar.h

 #ifndef BAR_H
 #define BAR_H
 #include <mylib.h>
 template < class T >
 class Bar{
    public: ...
           template <class S>
           void doSomething(Foo<S>*);
    private: ... 
 };
 #endif

bar.cpp

  ....
  template <class T> template <class S>
  void Bar<T>::doSomething(Foo<S>*p){
      ....
  }
  .....
  #include "bar.inc"

bar.inc

 template class Bar<int>;
 template class Bar<float>;
 template void Bar<int>::doSomething(Foo<int>*);
 template void Bar<float>::doSomething(Foo<float>*);

mylib.h

 #include <foo.h>
 #include <bar.h>

main.cpp

#include <mylib.h>
#include <common.h>

int main(){
    Foo<float> * pFoo = NULL;
    pFoo = new Foo<float>();

    Bar<float> * pBar = NULL;
    pBar = new Bar<float>();
    pBar->doSomething(pFoo);

    delete pFoo;
    delete pBar;

    return (0);
}

在我实例化对象的过程中,有人看到任何问题/错误吗?完整的错误信息是(我更改了类的名称并简化了代码以便更容易理解):

 g++ -O3 -Wall main.cpp -o ../bin/main -I../inc -L../lib -lmylib -lm
 /tmp/cciJHsKr.o: In function `main':
 main.cpp:(.text+0x19f): undefined reference to `void Bar<float>::doSomething<float>(Foo<float>*)'
 collect2: ld returned 1 exit status
 make: *** [main] Error 1

请注意,我分别编译了 foo.cpp 和 bar.cpp,因为我正在生成一个库。

 // Makefile for foo.cpp & bar.cpp
 INC=./inc
 SRC=./src
 LIB=./lib
 OBJ=./obj

 CC=g++
 CFLAGS=-O3 -Wall

 mylib: $(LIB)/mylib.a
      echo "mylib was created!..."

 $(LIB)/mylib.a: \
 $(OBJ)/bar.o \
 $(OBJ)/foo.o 
ar csr $(LIB)/mylib.a \
 $(OBJ)/bar.o \
 $(OBJ)/foo.o \


 $(OBJ)/bar.o: $(SRC)/bar.cpp
      $(CC) -c $(CFLAGS) $(SRC)/bar.cpp -I$(INC) \
      -o $(OBJ)/bar.o

【问题讨论】:

    标签: c++ templates class instantiation


    【解决方案1】:

    我解决了问题!

    bar.h

    #ifndef BAR_H
    #define BAR_H
    #include <mylib.h>
    template < class T >
    class Bar{
        public: ...
           template <class fooType>
           void doSomething(fooType*);
        private: ... 
    };
    #endif
    

    bar.cpp

    #include <bar.h>
    #include <foo.h>
    ...
    ...
    template <class T> template <class fooType>
    void Bar<T>::doSomething(fooType*p){
      ....
    }
    .....
    #include "bar.inc"
    

    bar.inc

    #include <foo.h>
    
    template class Bar<int>;
    template class Bar<float>;
    template void Bar<int>::doSomething(Foo<int>*);
    template void Bar<float>::doSomething(Foo<float>*);
    

    【讨论】:

      【解决方案2】:

      目前我还没有安装 GCC 的环境,所以我在这里瞎了眼。

      您的代码似乎存在一些问题(正如我的心理编译器所看到的那样)。

      1. 在 bar.cpp 中,您没有限定 doSomething() 函数的范围。鉴于它已在单独的标头中声明,您需要Bar::doSomething()。鉴于 Bar 是模板化的,您还需要提供绑定,即 Bar&lt;T&gt;::doSomething()

      2. 在 bar.cpp 中,模板绑定似乎是错误的方式(在您的示例中它们可以是任意的,但是),为了澄清,我会改变它们,使其如下:template &lt;class T&gt; template &lt;class S&gt; void Bar&lt;T&gt;::doSomething(Foo&lt;S&gt;*p){ ... }

      3. 最后main() 有一个问题,因为您没有在堆上创建Foo 对象-我认为编译器应该抓住这个(将Foo 分配给Foo*)。我猜你刚刚错过了new 关键字。 pFoo = new Foo&lt;float&gt;();

      【讨论】:

      • 您好,感谢您的评论!我编辑了我的原始帖子。您的观察是正确的,确实,原始源代码已经考虑了您提到的要点。因此,该错误不在提到的 3 点中的任何一个上。
      猜你喜欢
      • 1970-01-01
      • 2014-09-13
      • 1970-01-01
      • 2021-05-02
      • 2014-06-30
      • 2019-04-15
      • 2014-10-31
      • 1970-01-01
      • 2021-07-18
      相关资源
      最近更新 更多