// bslmf_integersequence.h                                            -*-C++-*-
#ifndef INCLUDED_BSLMF_INTEGERSEQUENCE
#define INCLUDED_BSLMF_INTEGERSEQUENCE

#include <bsls_ident.h>
BSLS_IDENT("$Id: $")

//@PURPOSE: Provide a template parameter pack of integers.
//
//@CLASSES:
//  bslmf::IntegerSequence: a compile-time sequence of integers
//
//@DESCRIPTION: This component defines a class template,
// `bslmf::IntegerSequence`, which can be used in parameter pack expansions.
//
// `bslmf::IntegerSequence` meets the requirements of the `integer_sequence`
// template introduced in the C++14 standard [intseq.intseq] and can be used in
// a client's code if the compiler supports the C++11 standard.
//
// Note, that this component has no (emulated) support for pre-standard C++11
// compilers, as its only purpose is to be used in deduction with template
// parameter packs.  There is no language support to emulate in earlier
// compilers.
//
///Usage
///-----
// In this section we show intended use of this component.
//
///Example 1: Pass C-array as a parameter to a function with variadic template
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// Suppose we want to initialize a C-Array of known size `t_N` with data read
// from a data source using a library class that provides a variadic template
// interface that loads a data of variable length into the supplied parameter
// pack.
//
// First, define a class template `DataReader`,
// ```
// template <std::size_t t_N>
// class DataReader {
//   public:
// ```
// Then, implement a method that loads the specified parameter pack `args` with
// data read from a data source.
// ```
//    template <class ...t_T>
//    void read(t_T*... args) const
//    {
//        static_assert(sizeof...(args) == t_N, "");
//        read_impl(args...);
//    }
// ```
// Next, for the test purpose provide simple implementation of the recursive
// variadic `read_impl` function that streams the index of the C-Array's
// element to `stdout`.
// ```
// private:
//     template <class t_U, class ...t_T>
//     void read_impl(t_U*, t_T*... args) const
//     {
//         printf("read element #%i\n",
//                static_cast<int>(t_N - 1 - sizeof...(args)));
//         read_impl(args...);
//     }
// ```
// Then, implement the recursion break condition.
// ```
//    void read_impl() const
//    {
//    }
// };
// ```
// Next, define a helper function template `readData` that expands the
// parameter pack of indices `t_I` and invokes the variadic template `read`
// method of the specified `reader` object.
// ```
// namespace {
// template<class t_R, class t_T, std::size_t... t_I>
// void readData(const t_R&  reader,
//               t_T      *data,
//               bslmf::IntegerSequence<std::size_t, t_I...>)
// {
//     reader.read(&data[t_I]...);
//         // In pseudocode, this is equivalent to:
//         // reader.read(&data[0],
//         //             &data[1],
//         //             &data[2],
//         //             ...
//         //             &data[t_N-1]);
// }
// }
// ```
// Finally, define a `data` C-Array and `reader` variables and pass them to the
// `readData` function as parameters.
// ```
// constexpr int      k_SIZE = 5;
// DataReader<k_SIZE> reader;
// int                data[k_SIZE] = {0};
//
// readData(reader,
//          data,
//          bslmf::IntegerSequence<size_t, 0, 1, 2, 3, 4>());
// ```
// Note that using a direct call to the `bslmf::IntegerSequence` constructor
// looks a bit clumsy here.  The better approach is to use alias template
// `bslmf::MakeIntegerSequence`, that creates a collection of increasing
// integer values, having the specified t_N-value length.  The usage example in
// that component shows this method more clearly.  But we can not afford its
// presence here to avoid a cycle/levelization violation.
//
// The streaming operator produces output in the following format on `stdout`:
// ```
// read element #0
// read element #1
// read element #2
// read element #3
// read element #4
// ```

#include <bslscm_version.h>

#include <bslmf_integralconstant.h>

#include <bsls_libraryfeatures.h>

#include <cstddef>  // 'std::size_t'

#ifdef BSLS_LIBRARYFEATURES_HAS_CPP14_INTEGER_SEQUENCE

namespace BloombergLP {
namespace bslmf {
                            // ======================
                            // struct IntegerSequence
                            // ======================

/// This class template represents a compile-time sequence of integers.
/// When passed as an argument to a function template, the specified
/// parameter pack `t_INTS` can be deduced and used a in pack expansion.
template <class t_T, t_T ...t_INTS>
struct IntegerSequence {

    // TYPES

    /// `value_type` is an alias to the template parameter `t_T` that
    /// represents an integer type to use for the elements of the sequence.
    typedef t_T value_type;

    // CLASS METHODS

    /// Return the number of elements in `t_INTS`.
    static constexpr std::size_t size() noexcept;
};

}  // close package namespace

// ============================================================================
//                      INLINE FUNCTION DEFINITIONS
// ============================================================================

                            // ----------------------
                            // struct IntegerSequence
                            // ----------------------

template <class t_T, t_T... t_INTS>
inline
constexpr std::size_t bslmf::IntegerSequence<t_T, t_INTS...>::size() noexcept
{
    return sizeof...(t_INTS);
}

}  // close enterprise namespace

#endif  // BSLS_LIBRARYFEATURES_HAS_CPP14_INTEGER_SEQUENCE

#endif  // INCLUDED_BSLMF_INTEGERSEQUENCE

// ----------------------------------------------------------------------------
// Copyright 2018 Bloomberg Finance L.P.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// ----------------------------- END-OF-FILE ----------------------------------
