如何实现非constexpr`std :: initializer_list`样式构造函数

时间:2015-05-24 16:04:18

标签: c++ templates c++11 constructor initializer-list

我尝试为轻量级数组类实现std::initializer_list构造函数,但后来我立即发现std::initializer_listconstexpr的问题。我通过使用可变参数模板构造函数和辅助函数以某种方式解决了它,但感觉就像这个单一目的的过度杀伤(IMO)。我对C ++的经验很短,所以我相信有更好更简单的方法。

我还考虑过从std::array使用移动构造函数?但移动表达的概念对我来说仍然不清楚。无论如何,这还值得考虑吗?

任何好的解决方案或建议都会对我有帮助。

template<typename T>
class Array:private boost::scoped_array<T>{
private:
    int m_length;

    int CountArguments(){
        return 0;
    }

    template<typename... Ts>
    int CountArguments(T const& t,Ts const&... ts){
        return 1+CountArguments(ts...);
    }

    void FillFromArguments(T* p){}

    template<typename... Ts>
    void FillFromArguments(T* p,T const& t,Ts const&... ts){
        *p++=t;
        FillFromArguments(p,ts...);
    }

public:
    Array(){}

    Array(int length):
    boost::scoped_array<T>(new T[length]),
    m_length(length){}

    template<typename... Ts>
    Array(T const& t,Ts const&... ts){
        m_length=CountArguments(t,ts...);
        boost::scoped_array<T>::reset(new T[m_length]);
        FillFromArguments(boost::scoped_array<T>::get(),t,ts...);
    }

    /* ... */

};

1 个答案:

答案 0 :(得分:0)

与问题评论一样,我没有看到std::initializer_list的问题。但你绝对不需要你写的任何成员函数。我们可以在构造函数中构造完整的数组:

template <typename... Ts,
          typename = std::enable_if_t<
              all_true<std::is_constructible<T, Ts&&>::value...>::value
          >>
Array(Ts&&... ts)
: boost::scoped_array<T>{new T[sizeof...(Ts)]{
    std::forward<Ts>(ts)...
}}
, length(sizeof...(Ts))
{
}

all_true来自Columbo here。这具有使用非默认可构造类型的额外好处:

struct X {
    X(int ) { }  
};

int main() {
    Array<X> t(1, 2, 3); // OK
}

虽然更简单的解决方案只是:

template <typename T>
class Array : private std::vector<T>
{
public:
    // constructor
    using std::vector<T>::vector;

    // accessors
    using std::vector<T>::size;
    using std::vector<T>::begin;
    using std::vector<T>::end;
    using std::vector<T>::operator[];

    // other functions that don't include push_back(), erase(), emplace(), ...    
};

让标准库处理所有事情。