我正在使用VS Express 2013尝试编译c ++项目。我已经创建了一个包含一些函数的模板类。该类及其功能都在一个头文件中。我已经包含了这个文件,我已经使用了这个类,我已经调用了它的函数,尽管所有Visual Studio都不会编译我不使用的类函数。我已经关闭了所有优化。我是否必须使用我编写的函数才能看到它是否编译?
这是功能:
void remove(ID id)
{
sdfgsdfg456456456456sfdsdf
}
该函数不应该编译。事实上,如果我使用这个函数,项目将无法编译,但如果我不使用该函数,项目将编译,即使我使用此类中的其他函数。
有解决方法吗?如果我在.cpp文件中实现该函数会发生同样的事情吗?
编辑:我忽略了提到它是一个模板类。我在。中添加了这些信息。
答案 0 :(得分:11)
正如评论中所揭示的那样,之所以发生这种情况,是因为remove()
是类模板中的一个函数。如果实际使用,编译器仅实例化模板代码;如果你不打电话给remove()
,它可能会有你想要的所有语法错误,没有人会抱怨。
更正式地说,§14.7.1的标准状态(强调我的):
类模板特化的隐式实例化导致 声明的隐式实例化,但不是 类成员函数的定义或默认参数
后来在同一部分:
实现不应隐式实例化函数 模板,成员模板,非虚拟成员函数,成员 class,或类模板的静态数据成员 需要实例化。
(“隐式”这个词在这里是关键;如果使用explicit template instantiation,编译器将立即尝试使用指定的类型实例化所有成员,如果没有编译则失败)
这不仅仅是一种优化;您可以利用此行为来实例化具有仅支持模板操作子集的类型的类模板。例如,假设您编写的模板类将与支持bar()
操作的类型一起使用,此外,还有一些模板类也支持baz()
。你可以这样做:
template<typename T>
class Foo
{
private:
T _myT;
public:
void bar()
{
_myT.bar();
}
void baz()
{
_myT.baz();
}
};
现在假设你也有这些:
struct BarAndBaz
{
void bar() {}
void baz() {}
};
struct BarOnly
{
void bar() {}
};
这将编译并运行得很好:
void f()
{
Foo<BarAndBaz> foo1;
foo1.bar();
foo1.baz();
Foo<BarOnly> foo2;
foo2.bar();
// don't try foo2.baz()!
// or template class Foo<BarOnly>!
}