I know that it's possible to declare a template in the header and its definition in a source file as long as I declare in advance the parameters it will be instantiated with. My question is: will putting the explicit instantiations in the .h file create problems? It seems to work but I've always seen people putting them in the source file, not in the .h
What I have in mind is the following
.h file
class foo
{
public:
template <typename T>
void do(const T& t);
};
template<> void foo::do<int>(const int&);
template<> void foo::do<std::string>(const std::string&);
.cpp file
template <int>
void foo::do(const int& t)
{
// Do something with t
}
template <std::string>
void foo::do(const std::string& t)
{
// Do something with t
}
These are called explicit specializations. Explicit instantiation is something else.
Putting those declarations in the header file is fine, and a very good idea. When compiling other source files, you want the compiler to know not to generate those specializations using the primary template.
Your syntax in the *.cpp file is wrong, though. The definitions should be more like the declarations:
template <>
void foo::do<int>(const int& t)
{
// Do something with t
}
Related
I have an overloaded function, their definitions are the same and only one parameter change.
So, I tried to create a template function but when I call it I got a symbol lookup error.
Header file
void func(Myobject obj);
void func(MySecondObject obj);
Source file
template<typename T>
void func(T obj) { obj.foo(); }
Test file
#include "MyHeaderFile.h"
func(MySecondObject()); // symbol lookup error at runtime
Thanks.
If you say
void func(Myobject obj);
void func(MySecondObject obj);
then you promise to the compiler that it will eventually find
void func(Myobject obj)
{ /* implementation */ }
void func(MySecondObject obj)
{ /* implementation */ }
Since you didn't provide these implementations (there are no definitions for these symbols you declared), you get an error.
What you can do however is this:
Header file
void func(Myobject obj);
void func(MySecondObject obj);
Source file
template<typename T>
void func_impl(T obj) { obj.foo(); }
void func(Myobject obj) { func_impl(obj); }
void func(MySecondObject obj) { func_impl(obj); }
This allows you to declare and define "real" (non-templated) functions for your users, but you can still implement all of them by delegating the work to the same template function. It is best practice to put the func_impl into an unnamed namespace (namespace /* no name here */ { /* code goes here */ }) which will make it internal to that translation unit (and also makes it clear that it's not intended to be seen/used by other code, without having to cross-reference the header).
(The following is already discussed at Why can templates only be implemented in the header file?).
An alternative approach is to declare the function template in the header, then define it in the source file and provide explicit instantiations for the types you want:
Header file
template<class T>
void func(T obj);
// Explicit instantiation declarations
extern template void func<Myobject>(Myobject obj);
extern template void func<MySecondObject>(MySecondObject obj);
Source file
template<typename T>
void func(T obj) { obj.foo(); }
// Explicit instantiation definitions
template void func<Myobject>(Myobject obj);
template void func<MySecondObject>(MySecondObject obj);
This approach is significantly more verbose, potentially confusing for users that are not template-affine, and trying to use it with the wrong type leads to linker errors instead of a nicer compiler error, so the first solution above can easily be the most appropriate.
Or you could define the entire template in the header file. There can be good reasons to avoid that though.
It seems that you want to have a template function with two explicit instantiations for MyObject and MySecondObject. Template function declaration should be in your header like that:
template<typename T>
void func(T obj);
Then in the corresponding source file you should provide generic implementation + explicit instantiations:
#include "header.hpp"
template<typename T>
void func(T obj)
{
obj.foo();
}
template void func<MyObject>(MyObject obj);
template void func<MySecondObject>(MySecondObject obj);
Then you can use that two versions in your code:
func(MyObject());
func(MySecondObject());
but call to func with another template parameter, e.g. func('c') will result in undefined reference.
cpp reference section "Explicit instantiation".
I would suggest defining the template specializations in the source file. It hides the template specializations in the current translation unit.
MyHeaderFile.h
template <typename T>
void func(T obj);
MyHeader.cpp
#include <iostream>
#include "MyHeaderFile.h"
template <typename T>
void func(T obj)
{
std::cout << "function name: " << __func__;
}
template void func<MySecondObject>(MySecondObject obj);
template void func<Myobject>(Myobject obj);
I hope this answer solves your problem.
I have a class:
// A.h
class A
{
void foo();
template <class T> void bar( T someVar );
}
#include "A.tcpp"
When I build it, I get linker errors. However, if the whole class would be a template, then the above example would build perfectly fine. So my question is:
How do I stick to the pattern of having ALL definitions in the cpp file, when having template member functions as opposed to having a template class?
If you are going to split a a class that has template functions and non template functions into a header file and a tcpp file then you only put the template definitions in the tcpp file. The non template definitions still needs to go into a regular cpp file.
Putting the non template code in the tcpp file includes it back into the header file and then that means it gets defined in every translation unit it gets included into.
In this case that means you should have
// A.h
class A
{
void foo();
template <class T> void bar( T someVar );
}
#include "A.tcpp"
// A.tcpp
template <class T> void A::bar( T someVar ) { some code; }
// A.cpp
#include "A.h"
void A::foo() { some code; }
I found the solution, it is not as nice as I would like, but it will do in my case. We can insert the following line at the end of the tcpp file:
template void A::bar<int>( int );
// And so on, for all types that should be supported.
It is called function template instantiation.
Suppose that I have two template functions declared in a header file:
template <typename T> void func1(const T& value);
template <typename T> void func2(const T& value);
And suppose that the implementation of these functions (also in a header file and not in a source file, because they are templates) uses some implementation helper function, which is also a template:
template <typename T> void helper(const T& value) {
// ...
}
template <typename T> void func1(const T& value) {
// ...
helper(value);
}
template <typename T> void func2(const T& value) {
// ...
helper(value);
}
In any source file that I include the header file, the helper function will be visible. I don't want that, because the helper function is just an implementation detail. Is there a way to hide the helper function?
A common approach (as used in many Boost libraries, for example) is to put the helper in a namespace called details, possibly in a separate header (included from the "public" header).
There's no way to prevent it from being visible, and callable, but this quite clearly indicates that it is part of the implementation, not the interface.
The established precedent is to put that sort of thing in a specially (i.e. consistently) named nested namespace. Boost uses namespace details, Loki uses namespace Private. Obviously nothing can prevent anyone from using the contents of those namespaces, but both names convey the meaning that their contents aren't intended for general consumption.
That being said, an easy alternative is to turn func1 and func2 from free function templates into static member function templates of some common class; this way, helper can simply be a private member of said class, invisible to the outside world:
struct funcs {
template<typename T>
static void func1(T const& value) {
// ...
helper(value);
}
template<typename T>
static void func2(T const& value) {
// ...
helper(value);
}
private:
template<typename T>
static void helper(T const& value) {
// ...
}
};
Two options off the top of my head:
Move all the implementation to an hpp file which you include at the bottom of your h file.
Refactor your code as class templates, then make the helpers private.
Since the user of your code needs to see the full definition of the func1 function, its implementation, nor its helper function implementation, cannot be hidden.
But if you move the implementation into another file, the user will only have to be confronted with the template declaration:
//templates.h
template< typename T > void f1( T& );
#include <templates_impl.h> // post-inclusion
And the definition:
// templates_impl.h
template< typename T > void f1_helper( T& ) {
}
template< typename T > void f1( T& ) {
// the function body
}
In C++20 you can now use modules.
For this you could create a module some_module.cppm holding all functions and marking only the interface (either the individual functions or a namespace) with export while not exposing the helper functions:
// some_module.cppm
export module some_module;
template <typename T>
void helper(const T& value) {
// ...
}
export
template <typename T>
void func1(const T& value) {
// ...
helper(value);
}
export
template <typename T>
void func2(const T& value) {
// ...
helper(value);
}
In the case above only the functions func1 and func2 are exported and can be accessed inside main.cpp:
// main.cpp
#include <cstdlib>
import some_module;
int main() {
func1(1.0);
func2(2.0);
return EXIT_SUCCESS;
}
In clang++12 you can compile this code with the following three commands:
clang++ -std=c++2b -fmodules-ts --precompile some_module.cppm -o some_module.pcm
clang++ -std=c++2b -fmodules-ts -c some_module.pcm -o some_module.o
clang++ -std=c++2b -fmodules-ts -fprebuilt-module-path=. some_module.o main.cpp -o main
./main
I would (as said before) make a template class, make all functions static and the helper function private. But besides that I'd also recommend making the constructor private as shown below:
template <typename T>
class Foo{
public:
static void func1(const T& value);
static void func2(const T& value);
private:
Foo();
static void helper(const T& value);
}
When you make the constructor private, the compiler won't allow instances of this template class. So the code below would become illegal:
#include "foo.h"
int main(){
int number = 0;
Foo<int>::func1(number); //allowed
Foo<int>::func2(number); //allowed
Foo<int>::helper(number); //not allowed, because it's private
Foo<int> foo_instance; //not allowed, because it's private
}
So why would someone want this? Because having different instances that are EXACTLY the same is something you probably never want. When the compiler tells you that the constructor of some class is private, then you can assume that having different instances of it would be unnecesarry.
I know you mean that you want to hide it so finely that callers have no way to find your helper functions as long as they don't change your code file. I know it so well because I have very similar needs recently.
So how about wrapping your helper functions in an anonymous namespace? This is recently the most elegant style I found:
namespace YourModule
{
namespace
{//Your helper functions}
//Your public functions
}
This practice effectively hides your internal functions from the outside. I can't find any way that a caller can access functions in anonymous namespaces.
It's usually not a good practice, as answered by #user3635700 , to convert your namespace to a class full of static functions, especially when you have templates of static variables like:
template <uint8_t TimerCode>
static uint16_t MillisecondsElapsed;
If this variable appears in a class, you'll have to initialize it somewhere outside the class! However, you can't do it because it's a template! WTF!
It seems that an anonymous namespace in the header file, which is criticized by some, is the only and the most perfect solution to our needs.
I have a template class definition that needs to be in the cpp file. Adopting from http://www.parashift.com/c++-faq-lite/templates.html#faq-35.13, I did something like this:
// File "foo.cpp"
#include <iostream>
#include "foo.h"
template<typename T> void foo()
{
std::cout << "Here I am!\n";
}
template void foo<int>();
I instantiate the template from the .cpp file. However, I need different types like foo(string) etc and I realized that I could only instantiate it once. How could I fix it?
Thanks.
You should be able to instantiate foo for each type you need.
template void foo<int>();
template void foo<double>();
template void foo<std::string>();
This is somewhat onerous, which is the reason many libraries tend to provide template function implementations in header files, so that any instantiation can be available to any cpp file which includes the header.
The template specialization should be in a separate translation unit (.cpp file) and the template (generic) definition in a header file.
In the foo.h
add the definition
template <typename T> void foo ()
{
std::cout << "Here I am! << std::endl;
}
In the foo.cpp use it
foo <int> ()
foo <std::string> ();
I have a class Foo which is used in a small standalone project. It has a class definition in Foo.h with the implementation for the class' member functions in an implementation file Foo.cpp.
First question - one of the member functions of class Foo is a template method Foo::doSomething(), is it correct that the implementation of this method should appear with the declaration of the function in Foo.h ?
The template parameter which Foo::doSomething() will be instantiated with is one of two Functor types - class CalcA and CalcB.
Should I:
(A) put the defintion and implementation of the two Functor classes all together in Foo.cpp (where they are actually used by the implementation of other Foo member functions to call Foo::doSomething).
(B) put the definition and implementation of the two Functor classes in Foo.h.
(C) should I put split the definition and implementation of the two Functors across Foo.h and Foo.cpp as would be done with an ordinary class?
General rule:
If foo::doSomething() is used outside foo.cpp (i.e. if it's public or protected, usually), it must go in the header.
If not, putting in in the cpp file is perfectly ok, and even a good idea (as it keeps the clutter away from the header file).
So, if the functors are only used in the cpp file, by all means put the template function there too. One can always refactor things later if this changes.
First you must understand templates mechanism. Templates are not compiled, they are instantiated when they are used and then their instantiation is compiled. So the compiler needs to have the full template definition in each module using the template function, in order to instantiate them first according to the parameters you've passed.
To solve your problem, there are three solutions but you'll see that they both lead to the same result.
Either you implement your whole templates in your header file inside the class definition (we use to suffix them with .hxx instead of .h in order to precise they're containing templates definitions):
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T& t) {
t.doSomething();
}
};
#endif
Or you can externalize the definition from the class, but still in the header file:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
#endif
Finally, you can implement template methods bodies in an external file (prefixed with .cxx for the same reason). It will contain methods' bodies but won't include "Foo.hxx". Instead, it's "Foo.hxx" that will include "Foo.cxx" after the class definition. This way, when the compiler resolves the #include directive, it finds the whole template definition in the same module, allowing it to instantiate it:
// Foo.hxx
#ifndef __FOO_HXX__
#define __FOO_HXX__
class Foo {
public:
template <class T>
void bar(const T&);
};
#include "Foo.cxx"
#endif
// Foo.cxx
template <class T>
void Foo::bar(const T& t) {
t.doSomething();
}
The choice between these 3 ways to implement templates is rather a matter of readability (and taste).
Second and third are equivalent in terms of generated code, but I'd rather not use the cxx file solution, because it often leads to stupid errors when you forget to invert the include.
Moreover, well-known C++ libraries like STL or Boost propose their code in header files only, which is a sign of good design. By using external definition inside headers, you clarify the definition of your class. You also prevent the compiler to automatically inline methods, which can sometimes lead to poor results according to Herb Sutter http://www.gotw.ca/gotw/033.htm
My default would be to put the definition for the member function templates right in the .h file, like this:
class Foo
{
public:
template<typename T> void DoSomething(T t);
};
// ... later...
template<typename T>
void Foo::DoSomething(T t)
{
// ...
}
If this is suboptimal for a particular case, then I'd take more heroic measures. Starting with #include-ing a .inc file with the definition at the end of the .h file, or possibly even doing explicit instantiations in the .cpp files where I needed the member function templates to be used.
The template method definition should indeed be in the header file of it the class it belongs to.
Like this:
class MyClass
{
template <typename T>
void foo(const T&)
{
// Definition
}
};
Or like this (note that the template method definition can be included from separate file after the class declaration)
class MyClass
{
template <typename T> void foo(const T&);
};
template <typename T>
void MyClass::foo(const T&)
{
// Definition
}
The rest is depends on the style you agreed on and your needs.
I would put the functor declaration (or even the definition if they are simple) into the header if I use them not only in Foo or if Foo has them as class member.