The member variable and constructor are dependent on the template parameter.

In C ++ 11, I would like to have a member variable in the class and a constructor to initialize it only if its default value was selected (only for supported types such as int, of course).

What are the recommended ways to achieve this (promotion allowed)?

Sort of:

template< int _x = -1 > struct C { C() {} // only available if _x != -1 C( int x ) : x( x ) {} // only available if _x == -1 // more methods that are common for all _x and refer to _x / x private: int x; // only available if _x == -1 // more members that are common for all _x }; 

Or, in another way: to optimize size and speed, I would like to use the compile-time constant instead of the value stored in the member variable if a different value was selected than the default template.

-

Here is an example to make everything clearer:

 template< int _size = -1 > struct Block { Block() { buf = mmap( _size, ... ); } // exists only when size!=-1 Block( int s ) { buf = mmap( size = s, ... ); } // exists only when size==-1 ~Block() { munmap( buf, getSize() ); } // should use the correct size int getSize() const { return ???; } // gets _size if !=-1, size otherwise // other methods that use buf and getSize() private: void *buf; const int size; // only exists for size == -1! }; 

This partially resolves:

 template< int _x > struct X { int getX() const { return _x; } }; template<> struct X< -1 > { X( x ) : x( x ) {} int getX() const { return _x; } private: int x; }; template< int _x = -1 > struct C : X< _x > { C() {} // only available if _x != -1 C( int x ) : X< _x >( x ) {} // only available if _x == -1 // more methods that are common for all _x and use this->getX() }; 

But what about C constructors and other / nicer solutions are available?

+4
source share
3 answers

Just an idea, but maybe it helps: you can try to use the base class only for minimal differences and "fake" the member variable if it does not exist to allow others to compile:

 template< int _x > class B { public: B() {} protected: static const int x = _x; }; template<> class B< -1 > { public: B( int i ) : x( i ) {} protected: int x; }; template< int _x = -1 > class C : public B<_x> { public: using B<_x>::B; // inherit B ctors void f() { if ( x == ... ) // uses either the member variable x or the static const int x! } }; 

but, as I said, this is just an idea ...

+4
source

Specialization is the way to go:

 template <int N> struct C { C(int n) : n_(n) { } int n; }; template <> struct C<-1> { C() { } C(int n) : n_(n) { } int n; }; 
+2
source

I am with Kerrek SB on this. Put your common code, namely, processing the runtime buffer into a common base class, create two derived classes: one for your buffer class of static size and one for your dynamic buffer class. Or better yet, according to general coding rules , use composition.

  class buffer_impl { public: buffer_impl(int size) : data_ {mmap( size, ... )}, size_ {size} {} ~buffer_impl() { munmap( data_, getSize() ); } int getSize() const noexcept { return size_; } // other buffer routines // ... private: void* data_; int size_; }; template <int _size = -1 > class buffer { // static size public: buffer() : impl_ {_size} {} static constexpr int getSize() noexcept { return _size; } private: buffer_impl impl_; }; template <> class buffer<-1> { // dynamic size public: buffer(int size) : impl_ {size} {} int getSize() const noexcept { return impl_.getSize(); } private: buffer_impl impl_; }; 
0
source

All Articles