gpt4 book ai didi

c++ - 模板方法特化链接错误

转载 作者:可可西里 更新时间:2023-11-01 16:31:14 26 4
gpt4 key购买 nike

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

// 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<float> 的链接错误特化。如果我将特化的定义放在头文件中,那么一切都会按预期进行。

我认为原因可能是该方法未显式实例化(尽管 template class 的完全特化不需要显式实例化以进行正确链接)。如果我尝试显式实例化该方法,则会收到此错误:

error C3416: 'MyClass::foo' : an explicit specialization may not be explicitly instantiated

所以问题是:

  • 有没有办法在 cpp 中定义特化?文件和链接正确吗?
  • 如果不是,为什么不呢?我可以显式实例化模板方法不专业就好了。为什么完全特化不一样?

最佳答案

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

  1. foo<int>()foo<float>()是成员模板的显式特化。这些不能出现在它们所属的类的定义中。标准说:

    (§14.7.3/3) [...] The definition of a class or class template shall precede the declaration of an explicit specialization for a member template of the class or class template. [...]

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

  2. foo<int>为例, 在头文件中有完整的定义,这意味着你必须把这个词 inline在定义之前;否则,如果头文件包含在多个翻译单元中,您将遇到链接器问题。

  3. foo<float>() 的特化在一个单独的文件中定义,该文件稍后链接到 main.cpp .这是可能的,但它需要在头文件中给出它的声明(你已经这样做了,但你必须在类定义之外进行):

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

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

    (§14.7.3/6) If a template, a member template or a member of a class template is explicitly specialized then that specialization shall be declared before the first use of that specialization that would cause an implicit instantiation to take place, in every translation unit in which such a use occurs; no diagnostic is required. [...]

  4. 由于所有特化都是显式(即完全特化,用你的话),所以不需要显式实例化,但它们是可能的(§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>();

关于c++ - 模板方法特化链接错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14078381/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com