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
什么';使用“s”时,专门化模板的正确方法是什么;外部模板“;? 我希望有人能指出在使用“外部模板类”和“模板类”来实现GNU C++显式实例化时,在模板类中专门化一个方法的正确方法。我试图用一个最简单的例子来概括这个问题,这个例子模仿了我真正的问题。似乎声明“extern template”意味着模板实例化,这会在专门化方法时导致错误。给定一个驱动程序:_C++_Templates_C++11 - Fatal编程技术网

什么';使用“s”时,专门化模板的正确方法是什么;外部模板“;? 我希望有人能指出在使用“外部模板类”和“模板类”来实现GNU C++显式实例化时,在模板类中专门化一个方法的正确方法。我试图用一个最简单的例子来概括这个问题,这个例子模仿了我真正的问题。似乎声明“extern template”意味着模板实例化,这会在专门化方法时导致错误。给定一个驱动程序:

什么';使用“s”时,专门化模板的正确方法是什么;外部模板“;? 我希望有人能指出在使用“外部模板类”和“模板类”来实现GNU C++显式实例化时,在模板类中专门化一个方法的正确方法。我试图用一个最简单的例子来概括这个问题,这个例子模仿了我真正的问题。似乎声明“extern template”意味着模板实例化,这会在专门化方法时导致错误。给定一个驱动程序:,c++,templates,c++11,C++,Templates,C++11,main.cc #include A_H #include <iostream> int main() { A<int> ai; A<long> al; std::cout << "ai=" << ai.get() << " al=" << al.get() << std::endl; return 0; } 但是,在我的真实示例中,这会导致使用g++4.1.2

main.cc

#include A_H
#include <iostream>

int main()
{
    A<int> ai;
    A<long> al;

    std::cout << "ai=" << ai.get() << " al=" << al.get() << std::endl;

    return 0;
}
但是,在我的真实示例中,这会导致使用g++4.1.2的程序崩溃(在使用g++4.4.4时)。我还没有缩小碰撞的确切原因(分段故障)。只有在调用A::get()时,堆栈指针才会损坏

我意识到显式模板实例化在这一点上是非标准的,但有人会认为我上面所做的工作会起作用吗?如果没有,正确的方法是什么

谢谢


但是你必须有
。如果省略
,声明将变成默认实现的显式实例化(
返回0
),这可能不是您想要的!即使您添加了
extern
,编译器也可以内联该默认实现;如果当您通过
-O2
时代码意外中断,您可能意外地遗漏了某个地方的

添加此答案以解决标题中的问题(模板实例化,而不一定是模板方法实例化)

这与函数声明/定义非常相似

  • 显式实例化声明:
    extern template类
    是一个声明,通常应该放在标题中
  • 显式实例化定义:
    模板类
    是一个定义,通常应该放在cpp中
  • 声明后的对象文件中不生成代码
  • 代码在包含定义的cpp的对象文件中生成
  • 如果没有显式实例化,则在实际使用模板时将发生隐式实例化。这将发生在使用模板的每个编译单元(对象文件)中
  • 如果遇到声明,则不会发生隐式实例化。这就是这种机制的要点——避免隐式实例化导致的目标代码重复,因为编译器不相信有一个编译单元负责实例化模板

更多信息。

c++0x删除了外部模板,因为它太难实现,没有删除?@VJo:
export
<添加了代码>外部(用于模板)。@James一定是新的,因为我还没有看到导出的模板far@VJo:是的,它在C++0x中是新的,尽管一些编译器支持它作为扩展已有一段时间了。VisualC++从2005开始就有了。@ VJO,杰姆斯:杰姆斯的最后一个回答[20:44 ]似乎把两个不同的东西混淆了(他的评论(18:40)更清楚了)。代码>导出模板由EDG实现,在C++03中标准化,并在C++11中删除,因为其他编译器供应商从未使用过它们<自2003年以来,EDG/GCC/IBM/Metrowerks/MSVC一直支持代码>外部模板(源代码:,另请参见),但仅在C++11中进行了标准化(类似于
long
),谢谢!您是否知道为什么“extern模板”或其依赖项需要关心专业化的存在?该方法的“名称”是int A::get()const,而显式实例化可以确保在链接时只有该方法的正确定义可用。@Roland通常,您可以执行类似于
模板类A{int iHaveNoGetFunctionAtAll();}a::get()
函数甚至不存在!这可能是编译器在应用“extern template”之前需要声明specilization的原因之一。答案很好,但您能否补充一下,将示例的第2行和第4行合并到单行
extern template int a::get()const中是否合法?这就是我来这里希望回答的问题。@Quuxplusone:不是用那种语法。如果需要显式专门化(必须定义),请使用
模板int A:get()const版本。如果希望显式实例化(通过模板定义),请不要在
模板
template int A::get()const
(在前面添加
extern
,使其不是一个定义)。如果我想要一个显式的extern专门化,但想要在一个声明中表达这个概念,该怎么办?不可能?您的意思是
模板类
应该放在与声明关联的.cpp文件中,还是放在其他地方使用该模板的cpp文件中?有一个你的意思的例子,我想,它应该放在关联的.cpp中,而不是一个只使用它的cpp,谢谢你做对了-它通常应该放在关联的cpp中。如果从那里不清楚的话,这就是答案的意图。
template<typename T>
struct A
{
    int get() const;
};

extern template class A<int>;
extern template class A<long>;
#include "a.h"

template<typename T>
int A<T>::get() const
{
    return 0;
}

template<>
int A<long>::get() const
{
    return 1;
}

template class A<int>;
template class A<long>;
 % g++ -Wall -g -D'A_H="a.h"' a.cc main.cc          
a.cc:10: error: specialization of 'int A<T>::get() const [with T = long int]' after instantiation
 %
template<typename T>
struct A
{
    int get() const;
};

template<typename T>
int A<T>::get() const
{
    return 0;
}

template<>
inline
int A<long>::get() const
{
    return 1;
}

extern template class A<int>;
extern template class A<long>;
#include "a-hack.h"

template class A<int>;
template class A<long>;
% g++ -Wall -g -D'A_H="a-hack.h"' a-hack.cc main.cc
% ./a.out 
ai=0 al=1
extern template class A<long>;
template <typename T> struct A { /*...*/ };
template<> int A<long>::get() const;
extern template class A<int>;
extern template class A<long>;
template<typename T> int freeGet() { return 0; }  // you can even add "inline" here safely!
template<> int freeGet<long>();  // this function is not inline (14.7.3/12)