分离没有'extern'的模板类的定义/实例化 [英] Separating definition/instantiation of template classes without 'extern'

查看:235
本文介绍了分离没有'extern'的模板类的定义/实例化的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

(不再新的)C ++ 11标准引入了模板的 extern 关键字。其目的是告诉编译器模板不应在使用点处被实例化,而是将在另一个翻译单元中实例化(因此在链接时将存在实例化) - 至少AFAIK。 p>

现在,即使在C ++ 11之前的版本中,我们使用类似的东西来分离模板类的声明/定义,以加快编译速度,例如像这样:



point.h :类定义

 code> template< int dim> struct Point {
...
void foo();
...
};

point.cpp :方法定义

  #includepoint.h
template< int dim>
void Point< dim> :: foo(){
...
}


b $ b

point_2d.cpp :类别实例化(2D版本)

  #include point.cpp
template struct Point< 2> ;;

point_3d.cpp :类别实例化(3D版本)

  #includepoint.cpp
template struct Point< 3> ;;

main.cpp :2D和3D点的使用

  #includepoint.h
int main(int,char **){
Point& p;
p.foo();
}

现在我想知道:




  • 我们的方法是有效的C ++(03或11)代码还是我们只是幸运的工作?

  • 对于C ++ 11,能够通过在 main.cpp 中包含 point.cpp 并声明 extern template< int dim> struct Point;


解决方案

代码,应该在C ++ 03和C ++ 11中工作。它被称为显式实例化:

  template struct Point< 2> 

在应用于类模板时,它显式实例化类模板的所有成员,电流变换单元。使用这种方法,创建模板库是很简单的,其中可能的模板参数的集合是预先已知的(例如在 Point 可以是2D和3D但是在C ++ 11中,当添加到显式实例化指令关键字 extern 时, :

  extern template struct Point< 2> 

它成为一个声明,而不是一个定义。这样的事情的行为类似于变量的通常的 extern 关键字。显式模板实例化声明可以以下列方式与显式实例化一起使用:

  // point.h 

template< int dim> struct Point {
...
void foo();
...
};

extern template struct Point< 2> ;;
extern template struct Point< 3>

#includepoint.hpp


// point.hpp

#includepoint.h

template< int dim>
void Point< dim> :: foo(){
...
}

// point.cpp

#include point.hpp

template struct Point< 2> ;;
template struct Point< 3> ;;

使用这样的代码,您可以获得与您的代码相同的结果,使用点<1> 点< 4> / code>类模板如果他们想要。无 extern template struct Point< 2> ;; extern template struct Point< 3> ;; 指令 Point 类模板将在用户代码中隐式实例化,甚至模板参数 2 3 c>,它减少了显式实例化的含义( template struct Point< 2> ;; template struct Point< 2> ;; )。


The (not so new anymore) C++11 standard introduced the extern keyword for templates. Its purpose is to tell the compiler that a template should not be instantiated at the point of usage, but that it will be instantiated in another translation unit (and thus there will be an instantiation available at link time) - at least AFAIK.

Now, even in the pre-C++11 era we used something similar to separate the declaration/definition of template classes from its instantiation in order to speed up compilation, e.g. like so:

point.h: class definition

template <int dim> struct Point {
  ...
  void foo();
  ...
};

point.cpp: method definitions

#include "point.h"
template <int dim>
void Point<dim>::foo() {
  ...
}

point_2d.cpp: class instantiation (2D version)

#include "point.cpp"
template struct Point<2>;

point_3d.cpp: class instantiation (3D version)

#include "point.cpp"
template struct Point<3>;

main.cpp: usage of 2D and 3D points

#include "point.h"
int main(int, char**) {
    Point<2> p;
    p.foo();
}

Now I am wondering:

  • Is our approach valid C++ (03 or 11) code or are we just lucky it worked?
  • With C++11, would we be able to achieve the same thing by including point.cpp in main.cpp and declaring extern template <int dim> struct Point;?

解决方案

Your approach is a valid C++ code and should work both in C++03 and C++11. It is called explicit instantiation:

template struct Point<2>;

While applying to class templates it explicitly instantiates all members of a class template for some template argument list in the current translation unit. With this approach it is simple to create the libraries of templates for which the set of possible template arguments is known in advance (as in your case when Point can be 2D and 3D but not 1D, 4D etc.).

In C++11 when you add to explicit instantiation directive keyword extern:

extern template struct Point<2>;

it becomes a declaration, not a definition. The behavior of such thing is similar to usual extern keyword for variables. Explicit template instantiation declaration can be used together with explicit instantiation in the following manner:

// point.h

template <int dim> struct Point {
  ...
  void foo();
  ...
};

extern template struct Point<2>;
extern template struct Point<3>;

#include "point.hpp"


// point.hpp

#include "point.h"

template <int dim>
void Point<dim>::foo() {
  ...
}

// point.cpp

#include "point.hpp"

template struct Point<2>;
template struct Point<3>;

With such code you achieve the same result as with your one but additionally you allow the users of your code to use Point<1>, Point<4> and other specializations of a Point class template if they want. Without extern template struct Point<2>; and extern template struct Point<3>; directives Point class template would be implicitly instantiated in the users code even for template arguments 2 and 3 that reduces the meaning of explicit instantiation (template struct Point<2>; and template struct Point<2>;).

这篇关于分离没有'extern'的模板类的定义/实例化的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆