为什么我的模板类中的某些函数没有被编译?

我正在使用 VS Express 2013 尝试编译一个 C++ 项目.我创建了一个具有一些功能的模板类.该类及其函数都在一个头文件中.我已经包含了这个文件,我已经使用了这个类,我已经调用了它的函数,尽管 Visual Studio 不会编译我没有使用的类的函数.我已经关闭了所有优化.我是否必须使用我编写的函数来查看它是否编译?

I am using VS Express 2013 trying to compile a c++ project. I've created a template class with some functions. The class and its functions are all in one header file. I've included the file, I've used the class, I've called functions from it, and despite all that visual studio won't compile the classes' functions that I'm not using. I've turned off all optimizations. Do I HAVE to use a function that I've written just to see that it compiles or not?

这是函数:

void remove(ID id)
{
    sdfgsdfg456456456456sfdsdf
}

该函数不应编译.事实上,如果我使用这个函数,项目将不会编译,但如果我不使用该函数,即使我使用这个类中的其他函数,项目也会编译.

The function shouldn't compile. And indeed the project won't compile if I do use this function, but if I don't use the function the project will compile, even if I use other functions from within this class.

有没有办法解决这个问题?如果我在 .cpp 文件中实现该功能,会发生同样的事情吗?

Is there a fix to this? Will the same thing happen if I implement the function in a .cpp file?

我忽略了它是一个模板类.我已经添加了该信息.

I neglected to mention it is a template class. I've added that information in.

推荐答案

正如评论中所揭示的,发生这种情况的原因是因为 remove() 是类模板中的一个函数.编译器只有在实际使用时才会实例化模板代码;如果你不调用 remove(),它可以有你想要的所有语法错误,没有人会抱怨.

As revealed in comments, the reason this is happening is because remove() is a function in a class template. The compiler only instantiates template code if it is actually used; if you don't call remove(), it can have all the syntax errors you want and nobody will complain.

更正式地,标准状态的 § 14.7.1(强调我的):

More formally, § 14.7.1 of the standard states (emphasis mine):

类模板特化的隐式实例化导致声明的隐式实例化,但不是类成员函数的定义或默认参数

The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not the definitions or default arguments, of the class member functions

稍后在同一部分:

一个实现不应隐式实例化一个函数模板,成员模板,非虚拟成员函数,成员类,或类模板的静态数据成员需要实例化.

An implementation shall not implicitly instantiate a function template, a member template, a non-virtual member function, a member class, or a static data member of a class template that does not require instantiation.

(此处隐式"一词是关键;如果您使用 显式模板实例化,编译器将立即尝试使用指定类型实例化所有成员,如果有任何成员无法编译则失败)

(the word "implicit" is key here; if you use explicit template instantiation, the compiler will immediately try to instantiate all members using the indicated type(s) and fail if any doesn't compile)

这不仅仅是一种优化;您可以利用此行为来实例化具有仅支持模板操作子集的类型的类模板.例如,假设您编写了一个模板类,该类将与支持 bar() 操作的类型一起使用,此外,某些类型还将支持 baz().你可以这样做:

This is not just an optimization; you can exploit this behavior to instantiate class templates with types that only support a subset of the template's operations. For example, suppose you write a template class that will be used with types that support a bar() operation, and in addition, some will also support baz(). You could do this:

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() {}
};

这将编译并运行得很好:

This will compile and run just fine:

void f()
{
   Foo<BarAndBaz> foo1;
   foo1.bar();
   foo1.baz();

   Foo<BarOnly> foo2;
   foo2.bar();
   // don't try foo2.baz()!
   // or template class Foo<BarOnly>!
}

相关文章