【发布时间】:2020-10-06 14:56:47
【问题描述】:
在 Memory.h 我有:
#pragma once
class Memory
{public:
template <typename T, typename ... TArgs>
static T* newAlloc(TArgs ... args)
{
return new T(args ...);
}
};
在 main.cpp 我有:
#include "Memory.h" // The template class is defined here
class Foo
{public:
Foo(int a, const char* c) {}
};
int main()
{
Memory::newAlloc<Foo>(7, "str");
}
即使在我粘贴到 Memory.h 之后 Foo 还没有完全定义,这也编译得很好。我对为什么会编译感到困惑。编译器粘贴到Memory.h后的等效代码是不是在main.cpp中是这样的:
class Memory
{
public:
static Foo* newAlloc(int a, const char* c)
{
return new Foo(a, c);
}
};
class Foo
{public:
Foo(int a, const char* c) {}
};
int main()
{
Memory::newAlloc(7, "str");
}
???因为这不能编译,所以我得到了错误:
'newAlloc' 未找到标识符 'newAlloc' 不是 记忆
基本上它想要 Foo 的完整定义。如果我将 Foo 类定义放在 Memory 之上,那么它编译得很好。所以考虑到我的第二个版本相当于模板实例化后的代码(是吗?)那么为什么第一个版本可以编译,而第二个没有?
我使用的是 Visual Studio 2019 16.4.5
【问题讨论】:
-
#include是一个简单的复制粘贴,但是 tempate 实例化并不是那么简单的机制。不需要将生成的代码实际放在任何地方,编译器知道它应该做什么就足够了。 -
Memory::newAlloc<Foo>在main中实例化,其中Foo的定义已完成。 -
你可以用模板做一些weird and wonderful things。
-
你在问著名的“两阶段查找”。
标签: c++ incomplete-type template-instantiation