Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 非模板类中的模板函数-H和CPP文件之间的划分_C++_Templates - Fatal编程技术网

C++ 非模板类中的模板函数-H和CPP文件之间的划分

C++ 非模板类中的模板函数-H和CPP文件之间的划分,c++,templates,C++,Templates,我(并且已经有很长一段时间)的印象是,您必须在.h文件中完全定义所有模板函数,以避免由于模板编译过程(非C++11)而出现多个定义错误 我正在阅读一位同事的代码,他有一个非模板类,其中声明了一个模板函数,他将函数声明与函数定义(在H中声明,在CPP中定义)分开。令我惊讶的是,它编译得很好 非模板类中的模板函数的编译方式与模板类中的函数的编译方式有区别吗?有人能解释一下这种区别是什么,或者我在哪里会感到困惑吗?有趣的一点是如何以及何时实例化模板。如果可以在链接时找到实例化,则模板定义不需要在头文件

我(并且已经有很长一段时间)的印象是,您必须在.h文件中完全定义所有模板函数,以避免由于模板编译过程(非C++11)而出现多个定义错误

我正在阅读一位同事的代码,他有一个非模板类,其中声明了一个模板函数,他将函数声明与函数定义(在H中声明,在CPP中定义)分开。令我惊讶的是,它编译得很好


非模板类中的模板函数的编译方式与模板类中的函数的编译方式有区别吗?有人能解释一下这种区别是什么,或者我在哪里会感到困惑吗?

有趣的一点是如何以及何时实例化模板。如果可以在链接时找到实例化,则模板定义不需要在头文件中可见

有时,显式实例化的原因如下:

  • 标题:

    struct X { 
        // function template _declaration_
        template <typename T> void test(const T&);
    };
    
    struct X{
    //函数模板声明_
    模板无效测试(常数T&);
    };
    
  • cpp:

    #include "X.h"
    
    // function template _definition_:
    template <typename T> 
        void X::test(const T&)
    {
    }
    
    // explicit function template _instantiation(s)_:
    template X::test<int>(const int&);    
    template X::test<std::string>(const std::string&);
    
    #包括“X.h”
    //函数模板\u定义\u:
    模板
    void X::test(常数T&)
    {
    }
    //显式函数模板实例化:
    模板X::测试(常量int&);
    模板X::test(const std::string&);
    

使用此示例,除非在其他翻译单元中使用模板的未实例化定义,否则链接将成功

在命名空间或类范围中定义的函数模板之间没有区别。是否在类模板内也无关紧要。重要的是,在项目中的某个时刻,任何使用过的函数模板(无论是成员还是非成员)都会被实例化。让我们看一下不同的情况:

  • 未使用的函数模板不需要实例化,因此它们的实现不需要在任何时候对编译器可见。这听起来很无聊,但很重要,例如在使用SFINAE方法时,类或函数模板被声明但未定义
  • 编译器将以允许跨不同翻译单元进行多个定义的形式实例化任何在使用位置定义的函数模板:只保留一个实例化。合并所有不同的定义是很重要的,因为如果采用函数模板的地址或在函数模板内使用状态变量,则可以检测到差异:每个实例化只能有一个这样的定义
  • 最有趣的设置是当使用函数模板时,函数模板的定义是而不是:在这种情况下,编译器无法实例化它。当编译器在不同的翻译单元中看到函数模板的定义时,它不知道要实例化哪个模板参数!A.好的,您总是可以显式地实例化一个模板一次。拥有多个显式实例化将创建多个定义的符号
  • 这些基本上是重要的选择。您不希望在标题中包含函数模板的定义,这通常是有充分理由的。例如,您不一定要拖入依赖项,否则就不会有依赖项。将函数模板的定义放在其他地方并显式实例化它是一件好事。此外,您可能希望减少编译时间,例如,避免在使用流的每个翻译单元中实例化整个I/O流和语言环境库。在C++ 2011中引入了外部模板,它允许声明特定模板(函数或类模板)在整个程序中被外部定义一次,并且不需要用特别的模板参数在每个报头中实例化它。 对于我刚才所说的更长的版本,包括示例,请看
    我上周末写了一篇关于这个主题的文章。

    他是否从自己的CPP之外调用了模板函数?在这个例子中,他没有-这会对情况产生什么影响?