“Multiple definition” when using (mock) header files for templates

大兔子大兔子 提交于 2019-11-28 14:13:46

Your problem occurs because function templates are treated differently at link time from "plain" free functions. Functions must obey the One Definition Rule (ODR); that is, they must be defined in no more than one translation unit. Otherwise, when you get to link time, you end up with multiple definition errors like the one you cited. This same rule also applies to classes, types, and objects in general.

This would seem to preclude the use of templates at all; they must be fully included in every translation unit in which they are used. However, the ODR makes an exception for a few cases. Quoting from Wikipedia:

Some things, like types, templates, and extern inline functions, can be defined in more than one translation unit. For a given entity, each definition must be the same. Non-extern objects and functions in different translation units are different entities, even if their names and types are the same.

This is why you don't run into multiple definition errors with the template functions. At link time, the linker finds the duplicate symbol definitions and removes all duplicates (as long as they are all equivalent; otherwise, this would be an error). Therefore, your program links successfully with exactly one definition of each required symbol.

For your case, your problem occurs because you are including non-template functions in more than one translation unit (everywhere that the .cpp file is included). There would be a few ways of fixing this:

  1. If the template functions are part of a class, you could move the non-template functions to lie in that class as well. This would bring it under the symbol-deduplicating umbrella of the owning template class.

  2. Mark the functions as inline.

  3. Break the non-template functions out into another .cpp file that you then compile separately. That will be the only translation unit that houses them.

In general you should compile .cpp file separately and link it later. But if you want (or must) do it this way, mark all non-template functions as inline. This should help.

As a good rule of thumb:

"Never ever include a .cpp file."

You shouldn't give these template implementation files a .cpp extension. Your build system might include them automatically then.

The conventionally used extensions for such files are e.g. .tcc or .icc. Add these to your project, as you would add other header files.
Don't include them in the project as separately build and linked translation units, if they are used with an #include statement from another header file.

UPDATE:
As you were asking for Code Blocks specifically, you'll just need to tweak your file extension settings a bit, to get these files included in your project correctly, and have them syntax colored as usual:

1. Add the new file type to the file extension settings

2. Add the file type to the project file extension settings Project->Project Tree->Edit file types & categories

As soon a .tcc file is added to the project now, it will be opened using the text editor, and syntax colored as usual:

The corresponding .hpp file looks like this

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!