// bsltf_emplacabletesttype.h                                         -*-C++-*-
#ifndef INCLUDED_BSLTF_EMPLACABLETESTTYPE
#define INCLUDED_BSLTF_EMPLACABLETESTTYPE

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

//@PURPOSE: Provide a non-allocating test class used to test `emplace` methods.
//
//@CLASSES:
//   bsltf::EmplacableTestType: non-allocating test class with 0..14 arguments
//
//@SEE_ALSO: bsltf_argumenttype, bsltf_templatetestfacility
//
//@DESCRIPTION: This component provides a (value-semantic) attribute class,
// `bsltf::EmplacableTestType`, that is used to ensure that arguments are
// forwarded correctly to a type's constructor.  This component is similar to
// `bsltf_allocemplacabletesttype`, but provides a type that does not allocate
// on construction.
//
///Attributes
///----------
// ```
// Name     Type                      Default
// -------  ------------------------  -------
// arg01    bsltf::ArgumentType< 1>   -1
// arg02    bsltf::ArgumentType< 2>   -1
// arg03    bsltf::ArgumentType< 3>   -1
// arg04    bsltf::ArgumentType< 4>   -1
// arg05    bsltf::ArgumentType< 5>   -1
// arg06    bsltf::ArgumentType< 6>   -1
// arg07    bsltf::ArgumentType< 7>   -1
// arg08    bsltf::ArgumentType< 8>   -1
// arg09    bsltf::ArgumentType< 9>   -1
// arg10    bsltf::ArgumentType<10>   -1
// arg11    bsltf::ArgumentType<11>   -1
// arg12    bsltf::ArgumentType<12>   -1
// arg13    bsltf::ArgumentType<13>   -1
// arg14    bsltf::ArgumentType<14>   -1
// ```
//
///Usage
///-----
// This section illustrates intended use of this component.
//
// See `bsltf_allocemplacabletesttype` for usage example.

#include <bslscm_version.h>

#include <bsltf_argumenttype.h>

namespace BloombergLP {
namespace bsltf {

                         // ========================
                         // class EmplacableTestType
                         // ========================

/// This class provides a test object used to check that the arguments
/// passed for creating an object with an in-place representation are of the
/// correct type and value.
class EmplacableTestType {

  public:
    // PUBLIC TYPES
    typedef bsltf::ArgumentType< 1> ArgType01;
    typedef bsltf::ArgumentType< 2> ArgType02;
    typedef bsltf::ArgumentType< 3> ArgType03;
    typedef bsltf::ArgumentType< 4> ArgType04;
    typedef bsltf::ArgumentType< 5> ArgType05;
    typedef bsltf::ArgumentType< 6> ArgType06;
    typedef bsltf::ArgumentType< 7> ArgType07;
    typedef bsltf::ArgumentType< 8> ArgType08;
    typedef bsltf::ArgumentType< 9> ArgType09;
    typedef bsltf::ArgumentType<10> ArgType10;
    typedef bsltf::ArgumentType<11> ArgType11;
    typedef bsltf::ArgumentType<12> ArgType12;
    typedef bsltf::ArgumentType<13> ArgType13;
    typedef bsltf::ArgumentType<14> ArgType14;

  private:
    // DATA
    ArgType01 d_arg01;
    ArgType02 d_arg02;
    ArgType03 d_arg03;
    ArgType04 d_arg04;
    ArgType05 d_arg05;
    ArgType06 d_arg06;
    ArgType07 d_arg07;
    ArgType08 d_arg08;
    ArgType09 d_arg09;
    ArgType10 d_arg10;
    ArgType11 d_arg11;
    ArgType12 d_arg12;
    ArgType13 d_arg13;
    ArgType14 d_arg14;

    // CLASS DATA

    // Track number of times the destructor is called.
    static int s_numDeletes;

  public:
    // CLASS METHODS

    /// Return the number of times an object of this type has been
    /// destroyed.
    static int getNumDeletes();

    // CREATORS

    /// Create an `EmplacableTestType` object by initializing corresponding
    /// attributes with the specified `arg01`..`arg14`, and initializing any
    /// remaining attributes with their default value (-1).
    EmplacableTestType();
    explicit EmplacableTestType(ArgType01 arg01);
    EmplacableTestType(ArgType01 arg01, ArgType02 arg02);
    EmplacableTestType(ArgType01 arg01, ArgType02 arg02, ArgType03 arg03);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08,
                       ArgType09 arg09);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08,
                       ArgType09 arg09,
                       ArgType10 arg10);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08,
                       ArgType09 arg09,
                       ArgType10 arg10,
                       ArgType11 arg11);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08,
                       ArgType09 arg09,
                       ArgType10 arg10,
                       ArgType11 arg11,
                       ArgType12 arg12);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08,
                       ArgType09 arg09,
                       ArgType10 arg10,
                       ArgType11 arg11,
                       ArgType12 arg12,
                       ArgType13 arg13);
    EmplacableTestType(ArgType01 arg01,
                       ArgType02 arg02,
                       ArgType03 arg03,
                       ArgType04 arg04,
                       ArgType05 arg05,
                       ArgType06 arg06,
                       ArgType07 arg07,
                       ArgType08 arg08,
                       ArgType09 arg09,
                       ArgType10 arg10,
                       ArgType11 arg11,
                       ArgType12 arg12,
                       ArgType13 arg13,
                       ArgType14 arg14);

    /// Create an in-place test object having the same value as the
    /// specified `original`.
    EmplacableTestType(const EmplacableTestType& original);

    /// Increment the count of calls to this destructor, and destroy this
    /// object.
    ~EmplacableTestType();

    // MANIPULATORS

    /// Assign to this object the value of the specified `rhs` object, and
    /// return a reference providing modifiable access to this object.  Note
    /// that this must be explicitly defined to silence compiler warnings on
    /// later versions of C++.
    EmplacableTestType& operator=(const EmplacableTestType& rhs);

    // ACCESSORS
    const ArgType01& arg01() const;
    const ArgType02& arg02() const;
    const ArgType03& arg03() const;
    const ArgType04& arg04() const;
    const ArgType05& arg05() const;
    const ArgType06& arg06() const;
    const ArgType07& arg07() const;
    const ArgType08& arg08() const;
    const ArgType09& arg09() const;
    const ArgType10& arg10() const;
    const ArgType11& arg11() const;
    const ArgType12& arg12() const;
    const ArgType13& arg13() const;

    /// Return the value of the correspondingly numbered argument that was
    /// passed to the constructor of this object.
    const ArgType14& arg14() const;

    /// Return `true` if the specified `other` object has the same value as
    /// this object, and `false` otherwise.  Two `EmplacableTestType`
    /// objects have the same value if each of their corresponding
    /// attributes have the same value.
    bool isEqual(const EmplacableTestType& other) const;
};

// FREE OPERATORS

/// Return `true` if the specified `lhs` and `rhs` objects have the same
/// value, and `false` otherwise.  Two `EmplacableTestType` objects have the
/// same value if each of their corresponding attributes have the same
/// value.
bool operator==(const EmplacableTestType& lhs, const EmplacableTestType& rhs);

/// Return `true` if the specified `lhs` and `rhs` objects do not have the
/// same value, and `false` otherwise.  Two `EmplacableTestType` objects do
/// not have the same value if any of their corresponding attributes do not
/// have the same value.
bool operator!=(const EmplacableTestType& lhs, const EmplacableTestType& rhs);

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

                        // ------------------------
                        // class EmplacableTestType
                        // ------------------------

// ACCESSORS
inline
const EmplacableTestType::ArgType01& EmplacableTestType::arg01() const
{
    return d_arg01;
}

inline
const EmplacableTestType::ArgType02& EmplacableTestType::arg02() const
{
    return d_arg02;
}

inline
const EmplacableTestType::ArgType03& EmplacableTestType::arg03() const
{
    return d_arg03;
}

inline
const EmplacableTestType::ArgType04& EmplacableTestType::arg04() const
{
    return d_arg04;
}

inline
const EmplacableTestType::ArgType05& EmplacableTestType::arg05() const
{
    return d_arg05;
}

inline
const EmplacableTestType::ArgType06& EmplacableTestType::arg06() const
{
    return d_arg06;
}

inline
const EmplacableTestType::ArgType07& EmplacableTestType::arg07() const
{
    return d_arg07;
}

inline
const EmplacableTestType::ArgType08& EmplacableTestType::arg08() const
{
    return d_arg08;
}

inline
const EmplacableTestType::ArgType09& EmplacableTestType::arg09() const
{
    return d_arg09;
}

inline
const EmplacableTestType::ArgType10& EmplacableTestType::arg10() const
{
    return d_arg10;
}

inline
const EmplacableTestType::ArgType11& EmplacableTestType::arg11() const
{
    return d_arg11;
}

inline
const EmplacableTestType::ArgType12& EmplacableTestType::arg12() const
{
    return d_arg12;
}

inline
const EmplacableTestType::ArgType13& EmplacableTestType::arg13() const
{
    return d_arg13;
}

inline
const EmplacableTestType::ArgType14& EmplacableTestType::arg14() const
{
    return d_arg14;
}

inline
bool EmplacableTestType::isEqual(const EmplacableTestType& other) const
{
    return d_arg01 == other.d_arg01
        && d_arg02 == other.d_arg02
        && d_arg03 == other.d_arg03
        && d_arg04 == other.d_arg04
        && d_arg05 == other.d_arg05
        && d_arg06 == other.d_arg06
        && d_arg07 == other.d_arg07
        && d_arg08 == other.d_arg08
        && d_arg09 == other.d_arg09
        && d_arg10 == other.d_arg10
        && d_arg11 == other.d_arg11
        && d_arg12 == other.d_arg12
        && d_arg13 == other.d_arg13
        && d_arg14 == other.d_arg14;
}

// FREE OPERATORS
inline
bool operator==(const EmplacableTestType& lhs, const EmplacableTestType& rhs)
{
    return lhs.isEqual(rhs);
}

inline
bool operator!=(const EmplacableTestType& lhs, const EmplacableTestType& rhs)
{
    return !lhs.isEqual(rhs);
}

}  // close package namespace
}  // close enterprise namespace

#endif

// ----------------------------------------------------------------------------
// Copyright 2016 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 ----------------------------------
