【问题标题】:member variable and constructor dependent on template parameter依赖于模板参数的成员变量和构造函数
【发布时间】:2013-03-30 22:30:15
【问题描述】:

在 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 的构造函数呢,还有其他/更好的解决方案吗?

【问题讨论】:

    标签: c++ templates c++11 constructor member


    【解决方案1】:

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

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

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

    【讨论】:

    • 哦,using 的把戏可能真的可以做到,谢谢!是否有替代方案,例如,如果我不仅有一个参数,如_x,还有_x_y
    • @Thomas B 的三个专业化?我知道,它并不能真正扩展,但这取决于您的用例的许多细节......恐怕我所知道的没有简单但通用的解决方案。
    • @Thomas 我的例子颠倒了,请看编辑后的答案!
    【解决方案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;
    };
    

    【讨论】:

    • 想象一下我的 C(在这两种情况下)包含一些常见的其他成员和方法。然后我可能会从您建议的专用类派生,但我将无法再访问它的构造函数。
    • @Thomas:反过来做:让模板继承自一个通用基类。
    【解决方案3】:

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

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-01-24
      • 1970-01-01
      • 1970-01-01
      • 2019-01-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-09
      相关资源
      最近更新 更多