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())?

iBug
  • 35,554
  • 7
  • 89
  • 134
  • 5
    Absolutely everything is possible as long as the observable behaviour of the program is in accordance with the standard. – n. m. could be an AI Dec 30 '17 at 10:26
  • @n.m. The instantiation point can change the observable behavior. – Oliv Dec 30 '17 at 12:29
  • @Oliv Instantiation doesn't entail generation or inclusion of any particular piece of object code. – n. m. could be an AI Dec 30 '17 at 15:03
  • @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) – Oliv Dec 30 '17 at 21:34
  • @Oliv 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. – n. m. could be an AI Dec 30 '17 at 22:09
  • @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. – Oliv Dec 31 '17 at 08:29
  • @Oliv 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. – n. m. could be an AI Dec 31 '17 at 16:18

4 Answers4

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, [...]

Oliv
  • 17,610
  • 1
  • 29
  • 72
  • 1
    This is a case where the compiler **must not** instantiate. It's not a compiler choice. – MSalters Dec 30 '17 at 12:15
  • @MSalters You mean that it would be appropriate to change "will not instantiate any member definition" to "must not instantiate..."? – Oliv Dec 30 '17 at 12:23
  • 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. – MSalters Dec 30 '17 at 12:28
  • OK I understand, there are(is) famous compiler which are not standard compliant, espescially on this subject. I make an edit. – Oliv Dec 30 '17 at 12:32
  • You mean that a standard-compliant compiler will **never** generate an instantiation of the class? – iBug Dec 30 '17 at 12:48
  • 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. – Oliv Dec 30 '17 at 13:11
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.

user0042
  • 7,917
  • 3
  • 24
  • 39
0

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

SoronelHaetir
  • 14,104
  • 1
  • 12
  • 23
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.