I saw an interesting thing but couldn't understand why.
template<class dataType>
Class A
{
AFnc();
}
template<> A<int>::AFnc() { }
Using only specialized template generates an error saying multiple definition of the same function. And it says it was generated at the same place.
But if I add
template<class dataType>
A<dataType>::AFnc()
{
}
Then it gets rid of the error.
Why ? Could someone please explain this behavior.
(You need to clean up your syntax. I assume that the actual code does not have all those syntax errors.)
Explicit specialization of template function is no longer a template, since it does not depend on any template parameters anymore. From the point of view of One Definition Rule (ODR) it is an "ordinary" function. And, as an "ordinary" function, it has to be declared in header file and defined only once in some implementation file. You apparently defined your specialization in header file, which is what leads to ODR violation if the header file gets included into multiple translation units (e.g. your "multiple definition" errors).
In your example, template<> void A<int>::AFnc() (I added void as return type) is no longer a template. This means that this definition
template<> void A<int>::AFnc() { }
must be moved from the header file to some implementation file. Meanwhile, in the header file you have to keep a non-defining declaration for this function
template<> void A<int>::AFnc(); // <- note, no function body
to let the compiler know that such specialization exists.
In general, remember the simple rule: if your function template still depends on some unspecified template parameters, it is a true template and it has to be defined in header file. But once you "fix" all the parameters (by explicit specialization) it is no longer a template. It becomes an ordinary function that has to be declared in header file and defined only once in some implementation file.
P.S. The above applies to non-inline functions. Inline functions can be (and are usually supposed to be) defined in header files.
P.P.S. The same logic applies to explicit specializations of static data members of template classes.
I guess, you put explicit instantiation in a header file. Then its code is emitted in every translation unit that includes that file. Just move this code
template<> A<int>::AFnc() { }
to .cpp file and it will be emitted only once.
You dont get this error with template method because rules for implicit instantiation are different.
Related
I believe that there are 4 situations where my question may have different answers. These situations are sorted by member vs. non-member functions and within vs. without a library.
Non-member function within a library
Suppose that I have defined a template function func in header func.h.
// func.h
template <typename T>
int func(T t){
//definition
}
I #include "func.h" in two cpp files of the same project/library/executable and call
//a.cpp
#include "func.h"
//stuff
int m = func<int>(3);
//stuff
and
//b.cpp
#include "func.h"
//stuff
int n = func<int>(27);
//stuff
My understanding is that these two cpp files should compile into their own object files. In what object file is func<int> instantiated? Why will the One Definition Rule not be violated? For this basic application of templates, is there any benefit to explicitly instantiating func<int> separate from its use?
Member function within a library
Suppose that func is instead a member function of some class Func.
// func.h
class Func {
template <typename T>
int func(T t){
//definition
}
};
Where will func be instantiated? Will func<int> be linked to or placed inline?
Member and Non-Member functions across libraries
Suppose that a.cpp and b.cpp are in different libraries that are compiled separately and later linked into an executable. Will the different libraries their own definitions of func<int>? At link time, why will the One Definition Rule not be violated?
Note: There is a related question of the same title here, but in a specific situation with one cpp file.
In what object file is func<int> instantiated?
In every object file (aka translation unit) that invokes it or takes an address of it when the template definition is available.
Why will the One Definition Rule not be violated?
Because the standard says so in [basic.def.odr].13.
Also see https://en.cppreference.com/w/cpp/language/definition
There can be more than one definition in a program of each of the following: class type, enumeration type, inline function, inline variable (since C++17), templated entity (template or member of template, but not full template specialization), as long as all of the following is true...
For this basic application of templates, is there any benefit to explicitly instantiating func<int> separate from its use?
In this case you get no inlining but possibly smaller code. If you use link-time code generation, then inlining may still happen.
All your questions do not really differ when it comes to answer. Regardless of template function being a member or a free function, it is going to be instantiated on first use (with given types) in each compilation unit (.cpp file).
From the compiler standpoint, ODR is not violated here, since there are no two prohibited definitions of templated function. Standard explicitly allows several definitions of templated functions.
Yet your intuition that you end up with definition of instantiated function twice in object files is correct. Luckily, ODR doesn't apply at this point. Instead, those definitions are generated with so-called 'weak' symbol - telling linker that those two symbols are identical, and it is free to pick one (or none and perform link-time optimization!)
I hate the boilerplate and Don't Repeat Yourself violations inherent in traditional class declarations in C++.
Is it possible to create a template with no template parameters, purely to enable the class to be defined in a header file without violating the One Definition Rule, in C++11?
There's no need for templates whatsoever.
If you want to write a header-only class, all you have to do is mark inline the functions that will be defined external to the class declaration:
#pragma once
struct some_class {
void implicitly_inline() { ... }
inline void explicitly_inline();
};
void some_class::explicitly_inline() { ... }
The occasional extra inline keyword is hardly such a burden as to change the entire definition of your class.
Is it possible to create a template with no template parameters
No. And you don't need for such workaround because...
to enable the class to be defined in a header file without violating the One Definition Rule
You can define a class in a header file without violating the One Definition Rule.
You can even define the member functions of a class in a header - which I think is the point of this question. Simply declare them all inline. If you define the member functions within the class definition, then they're implicitly inline.
There may be more than one definition of an inline function in the program as long as each definition appears in a different translation unit. For example, an inline function may be defined in a header file that is #include'd in multiple source files.
I was (and have been for a long time) under the impression that you had to fully define all template functions in your .h files to avoid multiple definition errors that occur due to the template compilation process (non C++11).
I was reading a co-worker's code, and he had a non-template class that had a template function declared in it, and he separated the function declaration from the function definition (declared in H, defined in CPP). It compiles and works fine to my surprise.
Is there a difference between how a template function in a non template class is compiled, and how a function in a template class is compiled? Can someone explain what that difference is or where I might be confused?
The interesting bit is how and when the template gets instantiated. If the instantiations can be found at link time, the template definition doesn't need to be visible in the header file.
Sometimes, explicit instantiations are cause like this:
header :
struct X {
// function template _declaration_
template <typename T> void test(const T&);
};
cpp:
#include "X.h"
// function template _definition_:
template <typename T>
void X::test(const T&)
{
}
// explicit function template _instantiation(s)_:
template X::test<int>(const int&);
template X::test<std::string>(const std::string&);
Using this sample, linking will succeed unless uninstantiated definitions of the template are used in other translation units
There is no difference between function templates defined in namespace or in class scope. It also doesn't matter whether is inside class template or not. What matter is that at some point in the project any used function template (whether member or non-member) is instantiated. Let's go over the different situations:
Unused function templates don't need to be instantiated and thus their implementation doesn't need to be visible to compiler at any point in time. This sounds boring but is important e.g. when using SFINAE approaches where class or function templates are declared but not defined.
Any function template which is defined where it is used will be instantiated by the compiler in a form which allows multiple definitions across different translation units: only one of the instantiations is retained. It is important that all the different definitions are merged because you could detect differences if you took the address of a function template or used a state variable inside the function template: there shall be only one of these for each instantiation.
The most interesting setup is where the definition of the function template is not seen when the function template is used: in this case the compiler cannot instantiate it. When the compiler sees a definition of the function template in a different translation unit it wouldn't know which template arguments to instantiate! A Catch 22? Well, you can always explicitly instantiate a template once. Having multiple explicit instantiations would create multiply defined symbols.
These are roughly the important options. There are often good reasons that you don't want to have the definition of a function template in the header. For example, you don't necessarily want to drag in dependencies you wouldn't have otherwise. Putting the definition of the function template somewhere else and explicitly instantiating it is a good thing. Also, you might want to reduce the compile time e.g. by avoiding to instantiate essentially the entire I/O stream and locale library in every translation unit using the stream. In C++ 2011 extern templates were introduced which allow the declaration that a particular template (either function or class template) is defined externally once for the entire program and there isn't any need to instantiate it in every header using particularly common template arguments.
For a longer version of what I just said, including examples have a look at a blog post
I wrote last weekend on this topic.
Any one of my C++ projects will generate a linker error unless I include an explicit template instantiation for every templated class/method/function I author and use.
STL classes seem to have no such problem.
Is there some simple code of conduct (pun intended) I can adhere to which allows deferred instantiation like that of STL?
Thanks for listening.
For templates you need to put all the template code and methods into headers rather than source files. The standard library does this.
You should put most parts of a template within the header file. This applies equally to template classes as well as template functions within normal classes.
The exception that you should know to this rule is that when you specialize a template, you need to put the specialization in the implementation/.cpp file because a specialization is a concrete type. The actual template definitions on the other hand will need to be run through multiple times, one for each template parameter type used with the template - so they must go in the header file (they're not concrete type-wise).
e.g. put:
template typename<T> foo(T val) { std::cerr << "DEFAULT"; }
in the header file and its specialization for an int:
template<> foo<int>(int val) { std::cerr << "INT"; }
in the cpp file because the int version is a concrete, fully defined function whereas the T version is a template definition which will be used many time to generate many concrete functions.
Most of the time a template class is defined completely in the header file. This allows the compiler to generate the body of code on the fly if it hasn't already come across the combination of function and template parameters that you're using.
You can still use a template with separate header and implementation files, but it's much less convenient. As you've discovered, you must anticipate each template parameter and put that combination in the implementation file, so that the compiler can generate the necessary code.
Does explicit template instantiation go in cpp or header file?
Assuming by "explicit template instantiation" you mean something like
template class Foo<int>; // explicit type instantiation
// or
template void Foo<int>(); // explicit function instantiation
then these must go in source files as they considered definitions and are consequently subject to the ODR.
I've always done it in a cpp file. In a header, it would violate the one definition rule, at least (in the usual case) when the header was included in more than one cpp file (though there are ways to avoid that, which can be useful under a few, specific circumstances).
Either one.
If you are declaring a specific instance, you might declare it in your cpp file. However, if you are declaring a class member or something that will be referenced from multiple cpp files, that would go in your header file.