5

在 C++11 中,我希望只有在选择了默认模板值的情况下才在类中有一个成员变量和一个用于初始化的构造函数(当然,仅适用于 int 等受支持的类型)。

有什么推荐的方法来实现这一点(允许提升)?

就像是:

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
};

或者,换一种说法:对于大小和速度优化,如果选择了模板默认值以外的其他值,我想使用编译时间常数而不是存储在成员变量中的值。

--

这是一个使一切更清晰的示例:

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!
};

这部分解决了它:

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()
};

但是 的构造函数C呢,还有其他/更好的解决方案吗?

4

3 回答 3

5

只是一个想法,但也许有帮助:您可以尝试仅将基类用于最小的差异,并在成员变量不存在时“伪造”成员变量以允许其余部分编译:

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's ctors

  void f()
  {
    if ( x == ... ) // uses either the member variable x or the static const int x!
  }
};

但正如我所说,这只是一个想法......

于 2013-04-08T19:15:48.057 回答
2

专业化是要走的路:

template <int N> struct C
{
    C(int n) : n_(n) { }
    int n;
};

template <> struct C<-1>
{
    C() { }
    C(int n) : n_(n) { }
    int n;
};
于 2013-04-08T18:09:25.373 回答
0

我和Kerrek SB 在这个问题上。将您的公共代码,即运行时缓冲区处理放在一个公共基类中,并创建两个派生类,一个用于静态大小的缓冲区类,一个用于动态缓冲区类。或者更好的是,根据通用编码指南,使用组合。

    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_;
    };
于 2013-04-09T07:24:04.333 回答