5

I'm reading the pbrt and it has defined a type:

template <int nSpectrumSamples>
class CoefficientSpectrum;
class RGBSpectrum : public CoefficientSpectrum<3> {
    using CoefficientSpectrum<3>::c;
typedef RGBSpectrum Spectrum;
// typedef SampledSpectrum Spectrum;

And the author said:

"We have not written the system such that the selection of which Spectrum implementation to use could be resolved at run time; to switch to a different representation, the entire system must be recompiled. One advantage to this design is that many of the various Spectrum methods can be implemented as short functions that can be inlined by the compiler, rather than being left as stand-alone functions that have to be invoked through the relatively slow virtual method call mechanism. Inlining frequently used short functions like these can give a substantial improvement in performance."

1.Why template can inline function but normal way can not?

2.Why do normal way has to use the virtual method?

Linkage to the entire header file: https://github.com/mmp/pbrt-v3/blob/master/src/core/spectrum.h

Y.Lex
  • 241
  • 1
  • 7
  • 4
    C++ supports static (compile-time) and dynamic (runtime) polymorphism. The former as templates, the latter as classes with virtual member functions. Both have its pros/cons. Static polymorphism must be resolved at compile time (drawback), but it does not suffer from runtime overhead of virtual functions (advantage). For the authors of that library, performance was likely a higher priority than runtime flexibility, so they decided to choose static polymorphism. – Daniel Langr Nov 28 '18 at 08:45
  • 1
    Also note that dynamic allocation is unrelated to the question. – Max Langhof Nov 28 '18 at 09:05
  • Tks for your note,Max.Actually,i 'm missing part of the quote. >A second advantage is that structures in the system that hold instances of the Spectrum type can hold them directly rather than needing to allocate them dynamically based on the spectral representation chosen at run time. – Y.Lex Nov 28 '18 at 09:12
  • 1
    @Y.Lex Dynamic polymorphism is typically implemented via base class pointer into which you store an address of dynamically-allocated instance of a derived class. – Daniel Langr Nov 28 '18 at 09:20

1 Answers1

7

To inline a function call, the compiler has to know 1. which function is called and 2. the exact code of that function. The whole purpose of virtual functions is to defer the choice which function is called to run-time, so compilers can obtain the above pieces of information only with sophisticated optimization techniques that require very specific circumstances1.

Both templates and virtual functions (i.e. polymorphy) are tools for encoding abstraction. The code that uses a CoefficientSpectrum does not really care about the implementation details of the spectrum, only that you can e.g. convert it to and from RGB - that's why it uses an abstraction (to avoid repeating the code for each kind of spectrum). As explained in the comment you quoted, using polymorphy for abstraction here would mean that the compiler has a hard time optimizing the code because it fundamentally defers the choice of implementation to run-time (which is sometimes useful but not strictly necessary here). By requiring the choice of implementation to be made at compile-time, the compiler can easily optimize (i.e. inline) the code.

1For example, some compilers are able to optimize away the std::function abstraction, which generally uses polymorphy for type erasure. Of course, this can only work if all the necessary information is available.

Max Langhof
  • 23,383
  • 5
  • 39
  • 72