I can't understand, why if we define static variable of usual (non-template) class in header, we have linker error, but in case of templates all works fine and moreover we will have single instance of static variable among all translation units:
It's template header (template.h):
// template.h
template<typename T>
class Templ {
public:
static int templStatic;
};
template<typename T> Templ<T>::templStatic = 0;
It's first unit using template (unit1.cpp)
// unit1.cpp
#include "template.h"
int method1() {
return Templ<void>::templStatic++;
}
Second unit here (unit2.cpp):
// unit2.cpp
#include "template.h"
int method2() {
return Templ<void>::templStatic++;
}
And, finally, main.cpp:
// main.cpp
#include <iostream>
int method1();
int method2();
int main(int argc, char** argv) {
std::cout << method1() << std::endl;
std::cout << method2() << std::endl;
}
After compilling, linking and executing this code, we will have following output:
0
1
So, why in case of templates all works fine (and as expected) ? How compiler or linker handle this (we can compile each .cpp file in separated calling of compiler, and then link them with caling to linker, so compiler and linker don't "see" all .cpp files at same time) ?
PS: My compiler: msvcpp 9 (but checked on mingw too)
It's because the definition of the static data member is itself a template. Allowing this is necessary for the same reason you are allowed to have a function template that's not inline multiple times in a program. You need the template to generate the resulting entity (say, a function, or a static data member). If you wouldn't be allowed to put the definition of a static data member, how would you instantiate the following
template<typename T>
struct F {
static int const value;
};
template<typename T>
int const F<T>::value = sizeof(T);
It's not known what T is - the Standard says the definition outside the class template is a template definition, in which the parameters are inherited from its class template owner.
I've made some experiment with GCC. In the following, we have one implicit instantiation of F<float>::value, and one explicit specialization of F<char>::value which has to be defined in a .cpp file to not cause duplicated symbol errors when included multiple times.
// Translation Unit 1
template<typename T>
struct F {
static int value;
};
template<typename T>
int F<T>::value = sizeof(T);
// this would belong into a .cpp file
template<> int F<char>::value = 2;
// this implicitly instantiates F<float>::value
int test = F<float>::value;
int main() { }
The second translation unit contains just another implicit instantiation of the same static data member
template<typename T>
struct F {
static int value;
};
template<typename T>
int F<T>::value = sizeof(T);
int test1 = F<float>::value;
Here is what we get with GCC - it makes each implicit instantiation into a weak symbols and sticks it into its own section here. Weak symbols will not cause errors when there exist multiple of them at link time. Instead, the linker will choose one instance, and discards the other ones assuming all of them are the same
objdump -Ct main1.o # =>
# cut down to the important ones
00000000 l df *ABS* 00000000 main1.cpp
0000000a l F .text 0000001e __static_initialization_and_destruction_0(int, int)
00000000 l d .data._ZN1FIfE5valueE 00000000 .data._ZN1FIfE5valueE
00000028 l F .text 0000001c global constructors keyed to _ZN1FIcE5valueE
00000000 g O .data 00000004 F<char>::value
00000000 g O .bss 00000004 test
00000000 g F .text 0000000a main
00000000 w O .data._ZN1FIfE5valueE 00000004 F<float>::value
So as we can see F<float>::value is a weak symbol which means the linker can see multiple of these at link time. test, main and F<char>::value are global (non-weak) symbols. Linking main1.o and main2.o together, we see in the map output (-Wl,-M) the following
# (mangled name)
.data._ZN1FIfE5valueE
0x080497ac 0x4 main1.o
0x080497ac F<float>::value
This indicates that actually it drops all except one instance.
There is solution, you can create a parent class and put the static variable in it, then make your template class inherit it privately, here's an example:
class Parent
{
protected:
static long count;
};
long Parent::count = 0;
template<typename T>
class TemplateClass: private Parent
{
private:
int mKey;
public:
TemplateClass():mKey(count++){}
long getKey(){return mKey;}
}
int main()
{
TemplateClass<int> obj1;
TemplateClass<double> obj2;
std::cout<<"Object 1 key is: "<<obj1.getKey()<<std::endl;
std::cout<<"Object 2 key is: "<<obj2.getKey()<<std::endl;
return 0;
}
Output will be:
Object 1 key is: 0
Object 2 key is: 1
It's because template code is not source code; it's instructions on how to write source code.
The non-template static variable is actual source code, and the compiler will attempt to do exactly what you say by including something in twice. Hence, you have to initialize the static variable in a .cpp file, and only reference it in the .h file describing the class. It's equivalent to a global variable declared through extern.
When the compiler sees
template<class T> Templ{...};
it does nothing except make a note that the template exists. As far as it is concerned, there is no source code associated with Templ.
The first time you actually refer to
Templ<int> Instance
the compiler looks at all the template<> code associated with Templ and uses it to construct a .h and a .cpp file (which exists only for the duration of compilation). Those files might look like this:
Temple_int.h
class Templ_int{
public:
static int templStatic;
};
Templ_int.cpp
#include "Templ_int.h"
Templ_int::templStatic = 0;
And every
Templ<int>
becomes a Templ_int.
Thus, the source code to initialize the static variable only exists once, in a .cpp file created by the compiler.
(Obviously, the actual compiler-specific implementation of this process would be robust against creating a class with a similar name to the template, etc.)
Related
I have the following code:
// template_header.hpp
#ifndef TEMPLATE_HEADER_HPP
#define TEMPLATE_HEADER_HPP
namespace template_header
{
template <int dim1>
/*static*/ constexpr int dim2 = 0;
template <>
/*static*/ constexpr int dim2<2> = 3;
template <>
/*static*/ constexpr int dim2<3> = 5;
}
#endif
// lib1.cpp
#include <array>
#include "template_header.hpp"
template <int dim1>
class lib1_class
{
public:
std::array< double, template_header::dim2<dim1> > ar1 = {0};
};
// lib2.cpp
#include <array>
#include "template_header.hpp"
template <int dim1>
class lib1_class
{
public:
std::array< double, template_header::dim2<dim1> > ar1 = {0};
};
If I compile any of the .cpp files with static uncommented, GCC gives me an "explicit template specialization cannot have a a storage class" error.
If static is commented, I can compile both .cpp files and then link them together as a shared library with g++ lib1.o lib2.o -shared -o shared_lib.so.
However, if I compile with static commented out with clang, I get no problems during compilation, but I get a "multiple definition of template_header::dim2<2>'" error during linking. If I uncomment static`, then everything compiles and links fine.
I'm pretty confused about this, firstly given that this answer indicates that, since my constexpr's happen in a namespace scope, they ought to automatically be static and therefore should pose no problem for the linker even if static is commented out.
Additionally, I don't understand why adding static beforehand would change how GCC compiles the .cpp files, given that it should be implicitly static.
Any explanation of the errors + possible fixes are appreciated.
Edit: I am using C++14.
So, without inline variables, I was able to get something achieving your goals working. The basic idea is to have a "backend" struct to hold static members and then fully specialize that struct to your options. This method has the added benefit of causing a compiler error if you attempt to access a member of the backend using a template parameter that has not been defined yet.
The header file would look like
#ifndef TEMPLATED_HEADER_HPP
#define TEMPLATED_HEADER_HPP
namespace template_header {
/**
* the "primary" template of the backend struct
* notice I leave the variable we want undefined!
* if you prefer to have a default for all other values of dim1
* you would put that here
*/
template<int dim1>
struct backend {};
template<>
struct backend<2> {
static constexpr int dim2 = 3;
};
template<>
struct backend<3> {
static constexpr int dim2 = 5;
};
/**
* Helper constexpr
* this is optional, but makes code outside this file more readable
* also, I named it in a way for your source files to be unchanged.
*/
template <int dim1>
constexpr dim2 = backend<dim1>::dim2;
}
#endif
I have a working version of this idea on Compiler Explorer which verifies that both this works with both GCC and clang. If you were to try to call dim2<dim1> where dim1 does not equal 2 or 3, then a compiler error complaining about backend<dim1>::dims not defined will be generated. You could add other members to the backend specializations, taking care to keep the names the same across the different values of dim1.
Total side note, why are you setting ar1 = {0};? From my reading of the std array reference, this would only set the first element in the array to 0.
I have a template class, which has two static member variables, one int and another an std::array<volatile uint_fast32_t, 8>. When I instantiate the template with two different classes (which are templates themselves) as template parameters, for one of the instantiations everything works perfectly, i.e. there is exactly one copy of both variables. However, for the other, the array appears in duplicate in the symbol table, and indeed my code has a bug that when I set a value in the array in one compilation unit, the change does not appear in another.
This is for an embedded system, which is the reason for this weird idiom of using static templates for a kind of compile-time polymorphism.
In code: Header declaring the class itself
//dacmux.h
namespace HAL {
template<typename dac_write_sequence_t,
unsigned int chans,
typename sample_t = uint_fast32_t>
struct dacmux {
private:
typedef std::array<volatile sample_t, chans> chans_t;
static chans_t channels;
static unsigned int nextchan;
...
};
//The static variables defined here,
//count on the compiler/linker to make sure
//there is exactly one definition
template<typename dac_write_sequence_t,
unsigned int chans,
typename sample_t>
typename dacmux<dac_write_sequence_t, chans, sample_t>::chans_t dacmux<dac_write_sequence_t, chans, sample_t>::channels{0};
template<typename dac_write_sequence_t, unsigned int chans, typename sample_t>
unsigned int dacmux<dac_write_sequence_t, chans, sample_t>::nextchan = 0;
template<typename dac_t, typename addr_t, typename en_t>
struct muxed_setter {
...
};
template<typename dac_t>
struct dac_setter {
...
};
}//namespace HAL
A header which distributes definitions of the hardware:
//Hardware_types.h
...
//Multiplexer for the internal DAC
typedef HAL::dacmux<HAL::muxed_setter<dac1, mux1_addr, mux1_en>, 8> mux1;
//Sequencer for writing the external DAC values
typedef HAL::dacmux<HAL::dac_setter<extdac1>, 8> extdac_sequencer;
...
The header Hardware_types.h is included in two source files, main.cpp, DebugConsole.cpp, both of which use both mux1 and extdac_sequencer.
As for as I understand, based on answers such as this one and many others, the compiler should take care that each of the static member variables is instantiated exactly once for each instantiation of the template?
However, when I set the values of extdac_sequencer::channels in DebugConsole.cpp, the changes are not reflected in an interrupt handler declared in main.cpp. The same works perfectly for mux1::channels. Indeed, an excerpt from the symbol table, extracted from the .elf by objdump -t:
20000280 l O .bss 00000004 _ZN3HAL6dacmuxINS_10dac_setterINS_6ti_dacINS_3SPIINS_5SPI_2EEEN5GPIOs5pin_tINS6_1BELj12EEENS_12_GLOBAL__N_110xx68_frameENSA_12command_xx68ENSA_12channel_xx68EEEEELj8EjE8nextchanE
...
20000254 l O .bss 00000020 _ZN3HAL6dacmuxINS_10dac_setterINS_6ti_dacINS_3SPIINS_5SPI_2EEEN5GPIOs5pin_tINS6_1BELj12EEENS_12_GLOBAL__N_110xx68_frameENSA_12command_xx68ENSA_12channel_xx68EEEEELj8EjE8channelsE
...
20000288 l O .bss 00000020 _ZN3HAL6dacmuxINS_10dac_setterINS_6ti_dacINS_3SPIINS_5SPI_2EEEN5GPIOs5pin_tINS6_1BELj12EEENS_12_GLOBAL__N_110xx68_frameENSA_12command_xx68ENSA_12channel_xx68EEEEELj8EjE8channelsE
...
20000234 w O .bss 00000020 _ZN3HAL6dacmuxINS_12muxed_setterIN4DACs11DAC_channelILj1EN5GPIOs5pin_tINS4_1AELj4EEEEENS4_12bit_stripe_tINS4_1CELj6ELj3EEENS5_ISA_Lj9EEEEELj8EjE8channelsE
...
2000027c w O .bss 00000004 _ZN3HAL6dacmuxINS_12muxed_setterIN4DACs11DAC_channelILj1EN5GPIOs5pin_tINS4_1AELj4EEEEENS4_12bit_stripe_tINS4_1CELj6ELj3EEENS5_ISA_Lj9EEEEELj8EjE8nextchanE
So the nextchan variable appears once per instantiation, as it should, and for mux1 so does channels. However, for extdac_sequencer, the channels variable is repeated, which I believe explains the bug.
Am I doing something wrong, or is this a compiler or linker bug?
Compiler: GCC arm-none-eabi 5.2.1 20151202
Linker: arm-none-eabi-ld 2.25.90.20151217
Linker options: -T mem.ld -T libs.ld -T sections.ld -nostartfiles -Xlinker --gc-sections -L"../ldscripts" -Wl,-Map,"Synth1Firmware.map" -Xlinker --cref --specs=nano.specs
Update:
I've narrowed down the conditions for this to happen:
If the first template parameter of dacmux is not itself a template, everything works, i.e. no duplicate symbol:
struct extdac1_setter {
template<typename sample_t>
inline static void update(sample_t val, unsigned int addr) {
extdac1::write_and_update(val, addr);
}
};
//Multiplexer for external DAC, works
typedef HAL::dacmux<extdac1_setter, 8> extdac_sequencer;
However, if the template parameter is templated itself, I get the duplicate symbol problem:
template<typename dac_t>
struct dac_setter {
template<typename sample_t>
inline static void update(sample_t val, unsigned int addr) {
dac_t::write_and_update(val, addr);
}
};
//Multiplexer for external DAC, this produces a duplicate symbol
typedef HAL::dacmux<dac_setter<extdac1>, 8> extdac_sequencer;
Here, extdac1 is itself, again, a template:
typedef HAL::DAC8568<dacspi, typename dacspi::nss> extdac1;
...and dacspi is a template, and so on. Also, in the case which does work, with the other instantation, while dac_write_sequence_t is a template, it isn't anymore a template of templates. So I'm starting to think that this is a problem with template recursion depth, i.e. ld isn't looking deep enough.
A further interesting observation: on exactly the same condition as having the duplicate symbol, the Eclipse syntax highlighter says "invalid template parameters" on the line declaring extdac_sequencer, although the actual compilation step goes through.
Turns out this was my sillyness: I was using an unnamed namespace in a header that defines the template HAL::DAC8568, which is defined as
template<typename spi_t, typename nss_t> using DAC8568 = ti_dac<spi_t, nss_t,
xx68_frame,
command_xx68,
channel_xx68>;
Here xx68_frame, command_xx68, and channel_xx68 are all defined in the unnamed namespace (which is of course the wrong thing to do in a header). This of course means that when instantiated from a different compilation unit, I get a different type for each of them and therefore a different type for DAC8568 and so on, so it's perfectly natural to get another instance of the static variable.
Changing the unnamed namespace to namespace detail fixed the problem immediately.
I am still somewhat baffled by the fact that the mangled names in the linker output seem identical. How can that be?
Anyway, we learn from this the following (some of which we knew already):
I'm an instantiation of the simpleton -pattern
unnamed namespaces in headers are truly evil
bugs stemming from the above can be quite subtle
I have a conceptual doubt which i'll try to put across using an example:
main.cpp
#include "array_list.cpp"
int main()
{
array_list list1;
return 0;
}
Scenario1:
array_list.cpp->
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int,int);
};
void array_list::set_element (int i,int a) {
list[i] = a;
}
Error:
main.obj : error LNK2005: "public: void __thiscall array_list::set_element(int,int)" (?set_element#array_list##QAEXHH#Z) already defined in array_list.obj
1>C:\Users\vrastog\Documents\Visual Studio 2012\Projects\C++ learning\Debug\list using arrays.exe : fatal error LNK1169: one or more multiply defined symbols found
Scenario 2:
array_list.cpp->
class array_list
{
private:
int list[10];
public:
array_list () {};
~array_list () {};
void set_element (int i,int a) {
list[i] = a;
}
};
Error: No error!!
Question: I understand the reason for error. The same method has been defined twice, once in main.obj and second in array_list.obj and hence, it should be an error.
My question is why does the second scenario work? Here also, since we have includes array_list.cpp in the main file, 'set_element' should have been defined twice here as well. What am I missing here?
Please don't include .cpp files.
In the first example, the function is defined out of class, you need to add inline, otherwise it's a multiple definition.
In the second example, the function is defined in the class definition, so it's an implicit inline function (it's like the compiler added the inline for you), that's why it's not causing multiple definitions.
In-class definition makes a method inline, and therefore it does not cause a multiple definition error in the object file.
An inline method should be implemented in every translation unit it is used in, so the inline method compiles into both object files.
C++ Standard Draft (n3797) 3.2.4: An inline function shall be defined in every translation unit in which it is odr-used.
Also 3.2.6 requires that these function should be exactly the same.
g++ implements this using weak symbols: inline functions are special exported functions that do not cause multiple definition error when linking.
Use a tool like nm under Linux and see for yourself. It emits a weak symbol into the object file:
$ nm arraylist.o
00000000 W _ZN10array_list11set_elementEii
(... ctors, dtors ...)
00000000 T main
Also, if you do not use the function, or the compiler inlines all occurrences, it may get optimized out.
Figuring if something wasn't broke, I'd break it, I decided to specialize a class I had so that it could be templated between float and double precision automagically.
I have the following [simplified] class declaration:
// Quatcam.h
#pragma once
#include <boost/math/quaternion.hpp>
#include <boost/numeric/ublas/matrix.hpp>
template<typename FloatType>
class QuaternionCamera
{
public:
QuaternionCamera();
void applyTranslation(boost::numeric::ublas::vector<FloatType> translationVector);
boost::numeric::ublas::matrix<FloatType> getTranslationMatrix();
protected:
boost::numeric::ublas::vector<FloatType> m_location;
boost::math::quaternion<FloatType> m_orientation;
};
I have defined the member functions in a .cpp file:
//Quatcam.cpp
#include "Quatcam.h"
using namespace boost::numeric::ublas;
template<typename FloatType>
QuaternionCamera<FloatType>::QuaternionCamera()
: m_location(3),
m_orientation(1,0,0,0)
{
m_location[0] = m_location[1] = m_location[2] = 0;
}
template<typename FloatType>
void QuaternionCamera<FloatType>::applyTranslation(boost::numeric::ublas::vector<FloatType> translationVector)
{
m_location += translationVector;
}
template<typename FloatType>
boost::numeric::ublas::matrix<FloatType> QuaternionCamera<FloatType>::getTranslationMatrix()
{
boost::numeric::ublas::matrix<FloatType> returnMatrix = boost::numeric::ublas::identity_matrix<FloatType>(4,4);
boost::numeric::ublas::vector<FloatType> invTrans = -m_location;
returnMatrix(3,0) = invTrans[0];
returnMatrix(3,1) = invTrans[1];
returnMatrix(3,2) = invTrans[2];
return returnMatrix;
}
This code by itself will happily compile into a .lib or .obj file, but attempting to use the class in situ results in linker errors. Here is my example main.cpp attempting to use the class:
#include "Quatcam.h"
#include <boost/numeric/ublas/io.hpp>
#include <iostream>
int main(int argc, char** argv)
{
QuaternionCamera<float> qcam;
boost::numeric::ublas::vector<float> loc(3);
loc[0] = 0;
loc[1] = 5;
loc[2] = 0;
qcam.applyTranslation(loc);
boost::numeric::ublas::matrix<float> qtm = qcam.getTranslationMatrix();
std::cout << "qtm: "<< qtm << std::endl;
return 0;
}
This code fails to link with an error for missing symbols for getTranslationMatrix and applyTranslation. I assume this is because I haven't technically specified a full specialization of the functions for the type float.
Question(s)
Given that the behavior is the same for any atomic input type (float, double, even int, etc...) and only affects the precision of the answers.
Is there a way to force the compiler to emit specializations for all of them without having to;
move all of the function definitions into the header file, or;
explicitly create specializations for all data types that would presumably involve a lot of copypasta?
Recommended links
Why can templates only be implemented in the header file?
Why do C++ template definitions need to be in the header?
Recommended Practice
Instead of moving the definitions from the .cpp to the header, rename the .cpp to .tpp and add #include "Quatcam.tpp" at the end of Quatcam.h.
This is how you typically split up the template declarations, and their definitions, while still having the definitions available for instantiation.
Note: If you follow this road, you should not compile the .tpp by itself, as you were doing with the .cpp.
Explicit Instantiation
You can explicitly instantiate the templates in question in your .cpp to provide them for the linker, but that requires that you know the exact types that you'd require an instantation of.
This means that if you only explicitly instantiate QuaternionCamera<float>, you'd still get a linker error if main.cpp tries to use QuaternionCamera<double>.
There's no way of forcing instantiation of all "atomic input types", you'll have to write them all out explicitly.
template class QuaternionCamera<float>; // explicit instantiation
template class QuaternionCamera<double>; // etc, etc...
You should put these functions into the header file, not into the .cpp source.
The compiler only creates function instantiations after the template argument deduction is complete. The resulting object file will contain a compiled function for each type that the template was used with.
However, .cpp files are compiled separately. So, when you compile Quatcam.cpp, the compiler doesn't find any instantiations for this type, and doesn't create a function body. This is why you end up with a linker error.
To put it simply, this is how your header should look like:
template<typename T>
class Foo {
void Print();
T data;
};
// If template arguments are specified, function body goes to .cpp
template<>
void Foo<float>::Print();
// Template arguments are incomplete, function body should remain in the header
template<typename T>
void Foo<T>::Print() {
std::cout << data;
}
And this should to the .cpp source:
template<>
void Foo<float>::Print() {
std::cout << floor(data);
}
With this question I'd like to better understand how C++ templates system works with regards to this question.
As far as I know, template-based classes and functions are usually placed into header files. This is due to the technical issue of managing generic data types, which characterstics are unknown in principle. As soon as they are known, the compiler can generate the executable code which is suited for the required data type.
In the header file something.h, our class shall be defined as follows:
template <typename T>
class Something
{
public:
void setElement (T &elem) {
element = elem;
}
T getElement () {
return element;
}
private:
T element;
};
Now let's suppose to split source and class definition:
The following class definition will be written in something.h:
template <typename T>
class Something
{
public:
void setElement (T &elem);
T getElement ();
private:
T element;
};
While the following methods will be written in something.cpp:
#include "something.h"
template <typename T>
void Something<T>::setElement (T &elem)
{
element = elem;
}
template <typename T>
T Something<T>::getElement ()
{
return element;
}
Unless we declare some specific-type instances inside something.cpp, if we compile it as object file we won't obtain any text section inside it:
dacav#mithril:<tmp>$ g++ something.cpp -c
dacav#mithril:<tmp>$ objdump -D something.o
something.o: file format elf64-x86-64
Disassembly of section .comment:
0000000000000000 <.comment>:
0: 00 47 43 add %al,0x43(%rdi)
3: 43 3a 20 rex.XB cmp (%r8),%spl
...
...
20: 34 2e xor $0x2e,%al
22: 31 00 xor %eax,(%rax)
dacav#mithril:<tmp>$
As Martin York shows we can force the compiler to generate the code for some specific data types in order to control which types can be used and which cannot. But what if we don't want any restriction?
If you want to be able to instantiate a template for arbitrary types, simply put everything that is needed for the instantiation in the header file. This means to put the function bodies (which need to be available to be instantiated) in the header file, not in a .cpp file.
If you want declarations and definitions in separate files simply for better structuring of the source code, you could use a scheme like this:
something.h
// Just the declaration
template<typename T>
class Something {
void foo();
};
// include the header file with the definitons
#include "something.impl.h"
something.impl.h
// Put definitions here
template<typename T>
void Something<T>::foo() {
}
You're stuffed, in short. The Standard did define an "export" keyword, that was supposed to export instantiable (i.e., the raw form, not a specific type) templates from a file. However, the reality is that virtually no major compilers support it and said that they would never support it. Therefore, it was removed from C++0x.