1

I tried to implement an std::initializer_list constructor for my lightweight array class, but then I immediately found a problem that std::initializer_list is a constexpr. I did solve it somehow by using variadic template constructors and helper functions, but it feels like an overkill (IMO) for this single purpose. My experience with C++ is short so I believe there is a better and simpler way.

I also thought about using a move constructor, from an std::array? but the concept of move expressions is still unclear to me. Anyway, is this also worth considering?

Any good solution or suggestion would help me.

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

    /* ... */

};
  • What about `std::initializer_list` didn't work exactly? I don't see why it wouldn't work. [Case in point](http://coliru.stacked-crooked.com/a/c370bee7921b4660) – chris May 24 '15 at 16:06
  • 1
    And how did you conclude `constexpr` was the problem? That doesn't even make sense to me. –  May 24 '15 at 16:08
  • @chris @hvd Shouldn't `constexpr` consist only of literals? to be evaluated in compile-time? –  May 24 '15 at 16:10
  • 3
    @xiver77 That's not exactly what `constexpr` means. Did you see any actual problem anywhere, or did you ask this question based on your understanding of `constexpr`, without testing? If you did see a real problem, could you edit your question to show the code that fails, and an explanation of why you think `constexpr` is the cause of it? –  May 24 '15 at 16:15
  • @hvd Interesting, I tested with a `rand()` call in an `std::initializer_list` and it compiles and works without any problem. –  May 24 '15 at 16:25
  • 1
    `constexpr` means it *can* be used at compile-time. If it *must* be at compile-time, there are templates. – chris May 24 '15 at 16:26

1 Answers1

0

As with the commentary on the question, I don't see the issue with std::initializer_list. But you definitely don't actually need any of the member functions that you wrote. We can just construct the full array in the constructor:

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))
{
}

Where all_true comes from Columbo here. This has the added benefit of working with non-default constructible types:

struct X {
    X(int ) { }  
};

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

Although an even simpler solution is just:

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

Let the standard library take care of everything.

Community
  • 1
  • 1
Barry
  • 286,269
  • 29
  • 621
  • 977