Avoiding explosive instances of C ++ template classes that accept int parameters

Say I have a C ++ class:

template<int N> class Text { public: Text() { } char _buf[N]; }; 

It just encapsulates the string C.

Now let's say that I am writing a method that will take another Text object with length M and copy its contents into this object.

 template<int N> class Text { public: Text() { } char _buf[N]; template<int M> void copy(const Text<M> &t) { strncpy(_buf, t.cstr(), N - 1); _buf[N - 1] = '\0'; } }; 

This will lead to an explosion of duplicate object code, where the only difference is that the constants N and M , especially if I use this copy method for objects with a lot of different N and M ?

Since the method itself does not depend on M , is there any other way to come close to such that I avoid this explosion of duplicate object code?

+5
source share
3 answers

The most obvious approach is to combine common bits into a base class, for example:

 class TextBase { public: char* text; int n; TextBase(char* text, int N): text(text), n(N) {} void copy(const TextBase &t) { strncpy(this->text, t.text, n - 1); this->text[n - 1] = '\0'; } }; template<int N> class Text: public TextBase { public: Text(): TextBase(_buf, N) { } char _buf[N]; }; 

It handles the size of an object to potentially improve code size. This should be obvious because this is the first thing that comes to my mind while still waking up. Instead of moving in terms of a base that takes a parameter in the form of an erase, it avoids the need for additional storage, for example. (this approach came to my mind when I was a little distracted from awakening):

 template<int N> class Text { public: Text() { } char _buf[N]; operator char const*() const { return this->_buf; } void copy(char const* source) { strncpy(this->_buf, source, N - 1); this->_buf[N - 1] = '\0'; } }; 
+3
source

As already mentioned, the solution can be a base class with a pure virtual method for receiving a buffer. No additional attribute is required, and _buf may be private.

Something like that:

 class TextBase { public: virtual const char* cstr() const =0; }; template<int N> class Text: public TextBase { public: Text() { } void copy( TextBase &t) { strncpy(_buf, t.cstr(), N - 1); _buf[N - 1] = '\0'; } protected: virtual const char* cstr() const { return _buf; }; private: char _buf[N]; // ... } 
+1
source

In general, I think C ++ 11 introduced an extern template to do this:

An explicit declaration of instantiation (an external template) prevents implicit instances: code that would otherwise cause implicit instantiation should use an explicit instantiation definition in another place in the program (usually in a different file: this can be used to reduce compilation time)

However, for your use case, you must explicitly create an instance of Text :: copy for all combinations of N and M, so this is not possible, and Dietmar's answer would be a better alternative.

0
source

Source: https://habr.com/ru/post/1246817/


All Articles