Is it possible that a compiled program does not contain an instantiated template class?
Asked Answered
K

4

11

Consider this code:

template <typename T>
class A {
    T x;
    // A bunch of functions
};

std::size_t s = sizeof(A<double>);

Assume the sizeof operator is the only place where an instantiation of A<double> is required. Is it possible that the compiled program does not contain relevant code for A<double> (e.g. A<double>::~A())?

Killer answered 30/12, 2017 at 10:10 Comment(7)
Absolutely everything is possible as long as the observable behaviour of the program is in accordance with the standard.Torrey
@n.m. The instantiation point can change the observable behavior.Toscana
@Toscana Instantiation doesn't entail generation or inclusion of any particular piece of object code.Torrey
@n.m. That songs like the begining of a pasionate debate about ontology! Are you talking about an instantiation that does not exist. (etymologie of exist, latin ex(s)istere, manifest itself, emerge)Toscana
@Toscana I'm talking about naming the right things with the right words. Instantiation is a process that turns a function template (a concept from the C++ language) into a function (a different concept from the C++ language), or a class template into a class. Whether or not that function is then turned into machine code instructions (not a concept from the C++ language) is a question not directly related to templates or any other part of the C++ language. It is about how well a compiler can eliminate unused code.Torrey
@n.m. What a disapointment! When I wrote the last comment, I thought you had understood that instantiation is a necessary condition to have code.Toscana
@Toscana I don't think the question makes a lot of sense. Pretending it does, we're talking about a sufficient condition, not a necessary one.Torrey
T
12

The class will be instantiated, but the compiler must not instantiate any member function definition, [temp.inst]/1:

[...] the class template specialization is implicitly instantiated when the specialization is referenced in a context that requires a completely-defined object type[...]

[temp.inst]/2:

The implicit instantiation of a class template specialization causes the implicit instantiation of the declarations, but not of the definitions, default arguments, or noexcept-specifiers of the class member functions, [...]

Toscana answered 30/12, 2017 at 10:22 Comment(6)
This is a case where the compiler must not instantiate. It's not a compiler choice.Externalism
@Externalism You mean that it would be appropriate to change "will not instantiate any member definition" to "must not instantiate..."?Toscana
I thought it was worth emphasizing that you can rely on the behaviour. You're not wrong, but the question was phrased to assume both behaviours are possible.Externalism
OK I understand, there are(is) famous compiler which are not standard compliant, espescially on this subject. I make an edit.Toscana
You mean that a standard-compliant compiler will never generate an instantiation of the class?Killer
It will instantiate the class in order to get the declaration of all members but it will never instantiate the member function definition if it is standard compliant. The reason is that the definition of a template function depends on its point of instantiation, so a compiler that would not be standard compliant could change your program observable behavior. So you will not find any member function code in the object file, you could still find typeid and vtable if the class had virtual member.Toscana
O
2

Is it possible that the compiled program does not contain relevant code for A<double> (e.g. A<double>::~A())?

Sure that's possible.

std::size_t s = sizeof(A<double>);

is just a compile time operation, and doesn't need any runtime instance of A<double>, so there's no need for constructors, destructors, or other relevant code.


Even if there would be explicit instantiations of template function code like follows

 if(sizeof(A<double>) <= 4) {
      A<double> a; // Instantiation of constructor and destructor
      a.x = 3.5;
 }

the compiler is allowed to optimize that code away.

Overskirt answered 30/12, 2017 at 10:14 Comment(0)
A
0

Yes, sizeof() does not need the member functions and so they may well not be generated. All sizeof needs are the data members.

Archetype answered 30/12, 2017 at 10:14 Comment(0)
V
0

I have built this code:

#include <cstddef>


template <typename T>
class A {
    T x;
    // A bunch of functions
};


int main(const int argc, const char* argv[])
{
    std::size_t s = sizeof(A<double>);
}

And launching objdump I get this output:

$ objdump -t a.out 

a.out:  file format Mach-O 64-bit x86-64

SYMBOL TABLE:
0000000100000000 g     F __TEXT,__text  __mh_execute_header
0000000100000f90 g     F __TEXT,__text  _main
0000000000000000         *UND*  dyld_stub_binder

Where we can see that no symbols associated to constructor/destructor have been generated.

Vociferance answered 30/12, 2017 at 11:52 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.