Note that there are some explanatory texts on larger screens.

plurals
  1. PORemoval of unused template instantiation's static members
    primarykey
    data
    text
    <p>I am currently involved embedded C++ development on am STM32 platform. Our team is evaluating the use of templates to parametrize drivers for various low-level hardware devices. </p> <p>All valid template specializations are known in advance thus we can give all valid specializations explicitly inside a implementation file (implementation and declaration separated). In fact, to us explicit specialization is quite useful since it helps to document viable parameter sets.</p> <pre><code>// file i2c_dev.h template&lt;typename traits&gt; struct i2c_dev { public: static void init(); static void send(); static bool busy(); ... private: static i2c_transfer periodic_transfer; // class with used-defined constructor }; // traits class for configuration A struct i2c_dev_traitsA { enum { I2Cx_BASE = I2C1_BASE , PORTx_BASE = GPIOB_BASE , PORTx_PIN_TX = PB08 , PORTx_PIN_RX = PB09 }; }; // traits class for configuration B, different I2C peripherial and pinout struct i2c_dev_traitsB { enum { I2Cx_BASE = I2C2_BASE , PORTx_BASE = GPIOA_BASE , PORTx_PIN_TX = PA01 , PORTx_PIN_RX = PA02 }; }; // file i2c_dev.cpp // Implementation of template functions template&lt;typename traits&gt; void i2c_devy&lt;traits&gt;::init() { ... } ... // explcitly specialize for all valid traits classes template class i2c_dev&lt;i2c_dev_traitsA&gt;; template class i2c_dev&lt;i2c_dev_traitsB&gt;; </code></pre> <p>Even though generally only one of the specializations will be actually used, the code generated for unused specializations gets removed from the final image by the linker, which is exactly what we want. </p> <p>However, the static member variables - <code>periodic_transfer</code> in the above sample - of each template specialization remain in the executable, as can be seen in the memory map generated by the <code>arm-none-eabi-nm</code> tool. This is probably due to the fact that <code>i2c_transfer</code> is not a POD but has a user-defined constructor. When the constructor is removed, turning the thing into a POD type, the static members also vanish. </p> <p>Is there a way to remove static non-POD members of explicitly instantiated, but unused templates?</p> <p>Regards, Arne</p> <p>Edit #1: After rethinking the problem I came up with the following solution, which apparently fixes the problem.</p> <p>When class <code>i2c_transfer</code> which in fact has it's constructors only for clarity and ease of use, has its data members moved into a POD base class <code>i2c_transfer_pod</code> like this:</p> <pre><code> struct i2c_transfer_pod { protected: uint16_t m_size; char* m_buffer; }; struct i2c_transfer : public i2c_transfer_pod { public: i2c_transfer(); i2c_transfer(i2c_direction_enum dir, char*buffer, uint16_t count); bool failed(); bool succeeded(); }; </code></pre> <p>Then, the static members of unused <code>i2c_dev&lt;traits&gt;</code> specializations are also removed from the final executable (as the map file suggests).</p> <p>Edit #2: Although answering one-self feels a bit lame.. I would kindly request comments on the proposed solution. Is there possibly a more elegant way? Is the compiler really (as I presume) optimizing away the additional derivation?</p> <p>Edit #3: I close the question since the solution works for me. Would be nice to have deeper insight into the reason for the observed behaviour.</p> <p>The compiler in question is <code>arm-none-eabi-gcc (Sourcery G++ Lite 2011.03-42) 4.5.2</code> </p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload