当前位置: 首页 > 知识库问答 >
问题:

模板方法专门化链接错误

廉博赡
2023-03-14

考虑以下头文件和源文件:

// main.cpp
#include "myClass.h"

int main()
{
  MyClass m;
  m.foo<double>();
  m.foo<float>();
}
// myClass.h
#pragma once

#include <iostream>

using namespace std;

class MyClass
{
public:

  template <typename T>
  void foo()
  {
    cout << "Template function<T> called" << endl;
  }

  template <>
  void foo<int>()
  {
    cout << "Template function<int> called" << endl;
  }

  template <>
  void foo<float>();

};
// myClass.cpp
#include "myClass.h"

template <>
void MyClass::foo<float>()
{
  cout << "Template function<float> called" << endl;
}

我在foo中发现一个链接错误

我认为原因可能是该方法没有显式实例化(尽管模板类的完全专门化不需要显式实例化来正确链接)。如果我尝试显式实例化该方法,我会遇到以下错误:

错误C3416:'MyClass::foo':显式特化可能无法显式实例化

所以问题是:

  • 有没有办法在cpp文件中定义专门化并正确链接

共有1个答案

微生昌勋
2023-03-14

虽然WhozCraig的答案(现已删除)提供了解决您问题的正确代码,但以下是对您的问题的一些直接回答,包括对代码的评论:

>

  • foo

    (§14.7.3/3) [...] 类或类模板的定义应在声明该类或类模板的成员模板的明确专业化之前进行。[...]

    所以你必须把它们放在类定义之后。

    foo的情况下

    foo的专门化

      template <>
      void MyClass::foo<float>();
    

    这是必需的,因为标准中的另一条声明:

    (§14.7.3/6)如果模板、成员模板或类模板的成员显式专业化,则应在第一次使用该专业化之前声明该专业化,这将导致隐式实例化发生,在发生此类使用的每个翻译单元中;不需要诊断。[...]

    由于所有专业化都是显式的(即完全专业化,用你的话来说),因此不需要显式实例化,但它们是可能的(§14.7.2)。您可以将它们放在. cpp文件的末尾,语法为:

    template void MyClass::foo<float>();
    template void MyClass::foo<int>();
    

    同样,这只对没有自己显式专门化的类型真正有用。

    因此,头文件和实现文件的正确代码如下所示:

    .h文件

    class MyClass
    {
    public:
      template <typename T> void foo()
      { cout << "Template function<T> called" << endl; }
    };
    
    template <> inline void MyClass::foo<int>()
    { cout << "Template function<int> called" << endl; }
    
    template <> void MyClass::foo<float>();
    

    .cpp:

    #include "myClass.h"
    
    template <> void MyClass::foo<float>()
    { cout << "Template function<float> called" << endl; }
    
    /* This is unnecessary for float, but may be useful for
       types that do not have their own explicit specializations: */
    template void MyClass::foo<float>();
    

  •  类似资料:
    • 对于DynamicMessage,我想使用不同的处理方式,所以我尝试了 但它给出了编译错误 com中的“addMessageToResult(Message,Descriptor,Builder)”。谷歌。云垂直方向。电信公司。taap。数据流。数据摄取。常见的解析器。CSVParserDynamicMessage与com中的addMessageToResult(Message,Descripto

    • 还尝试在专门化的中进行模板方法专门化: 这一次它编译,但调用原始方法,即 解决方案

    • 问题内容: 这是我的代码: 它运作良好。但是当我尝试添加这个 我遇到编译器错误:«int MyClass :: DoSomething()»的«>»令牌模板标识«DoSomething <0>»之前的无效显式专门化与任何模板声明都不匹配 我使用g ++ 4.6.1应该怎么做? 问题答案: 不幸的是,如果不对外部模板进行特殊化处理,就不能对作为类模板成员的模板进行特殊处理: C ++ 11 14.7

    • 我有几个模板参数的模板结构 此结构适用于所有模板,但结果无效的情况除外。我知道,不能实现为void类型,所以我当前的解决方案是使用如下的部分专门化: 这允许执行以下操作: 有没有一种方法可以使编译而不会在C 14标准中进行部分类特化?我可以使用和类型trait组合,但我想找到是否有一种方法: > 模板类方法的特殊化部分显式 模板类方法的实例化

    • 在本文中,他们说(c)是(b)的显式专门化。我的疑问是,为什么我们不能说它是(a)的显式专门化?因为我们可以为任何特定类型专门化模板。所以,当专门化int*时,为什么他们说(c)显式专门化(b)。 任何评论都将有助于理解事情。