// bslmf_typeidentity.h                                               -*-C++-*-
#ifndef INCLUDED_BSLMF_TYPEIDENTITY
#define INCLUDED_BSLMF_TYPEIDENTITY

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

//@PURPOSE: Provide a template metafunction that returns its argument.
//
//@CLASSES:
//  bsl::type_identity: template metafunction that returns its argument.
//  bsl::type_identity_t: alias for the return type of 'type_identity'
//
//@MACROS:
//  BSLMF_TYPEIDENTITY_T: Macro equivalent to 'bsl::type_identity_t' for C++03
//
//@SEE_ALSO:
//
//@DESCRIPTION: This component provides a trivial template metafunction class,
// 'bsl::type_identity' that takes one type template argument and produces the
// argument type as its result; i.e., 'bsl::type_identity<t_TYPE>::type' is
// simply an alias for 't_TYPE'.  This metafunction is used in situations where
// a no-op metafunction is desired or where template type deduction should be
// suppressed.  This component also provides, for C++11 and later, an alias,
// 'bsl::type_identity_t' such that 'bsl::type_identity_t<t_TYPE>' is short
// hand for 'typename bsl::type_identity<t_TYPE>::type'.
//
// The templates in this component have identical functionality to the standard
// templates, 'std::type_identity' and 'std::type_identity_t' defined in the
// '<type_traits>' header starting with C++20.
//
///Usage
///-----
//
///Example 1: Requiring explicit function template arguments
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// A function template can often deduce the types of its arguments, but
// sometimes we wish to prevent such deduction and require the user to supply
// the desired type explicitly.  In this example, we'll declare a cast
// function, 'implicitCast', that is invoked 'implicitCast<T>(arg)'.  The goal
// is cast the 'arg' to type 'T', but only if 'arg' is implicitly convertible
// to 'T'.
//
// First, we'll define a type 'TestType', that is implicitly convertible from
// 'int' but only explicitly convertible from 'const char *':
//..
//  struct TestType {
//      TestType(int) { }                                           // IMPLICIT
//      explicit TestType(const char*) { }
//  };
//..
// Next, we'll define 'implicitCastNAIVE', a naive and insufficient attempt at
// defining 'implicitCast':
//..
//  template <class t_TYPE>
//  t_TYPE implicitCastNAIVE(t_TYPE arg)
//  {
//      return arg;
//  }
//..
// Next, we try to use 'implicitCastNAIVE'.  The first invocation below
// correctly casts an 'int' to 'TestType'.  The second invocation should, and
// does, fail to compile because 'const char*' is not implicitly convertible to
// 'TestType'.  In the third invocation, we forgot the '<TestType>' template
// parameter.  Surprisingly (for the user), the code compiles anyway because
// 'implicitCastNAIVE' *deduced* 't_TYPE' to be 'const char*' and returns its
// argument unmodified, i.e., doing no casting whatsoever:
//..
//  TestType v1(implicitCastNAIVE<TestType>(5));      // OK
//  TestType v2(implicitCastNAIVE<TestType>("bye"));  // Fails correctly.
//  TestType v3(implicitCastNAIVE("hello"));          // Succeeds incorrectly.
//..
// Now, we implement 'implicitCast' correctly, using 'bsl::type_identity' to
// prevent implicit template-argument deduction:
//..
//  template <class t_TYPE>
//  t_TYPE implicitCast(typename bsl::type_identity<t_TYPE>::type arg)
//  {
//      return arg;
//  }
//..
// Finally, we try using 'implicitCast' both correctly and incorrectly.  As
// before, the first invocation below correctly casts an 'int' to 'TestType'
// and second invocation correctly fails to compile.  Unlike the
// 'implicitCastNAIVE' example, however, the third invocation correctly fails
// to compile because 't_TYPE' is not deduceable for a parameter of type
// 'bsl::type_identity<t_TYPE>::type'.
//..
//  TestType v4(implicitCast<TestType>(5));      // OK
//  TestType v5(implicitCast<TestType>("bye"));  // Fails correctly.
//  TestType v6(implicitCast("hello"));          // Fails correctly.
//..
// Note that 'typename bsl::type_identity<t_TYPE>::type' can be replaced by the
// more concise 'bsl::type_identity_t<t_TYPE>' (compatible with C++11 and
// later) or 'BSLMF_TYPEIDENTITY_T(t_TYPE)' (compatible with all C++ versions).
//
///Example 2: preventing ambiguous argument deduction in function templates
///- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
// In this example, we illustrate how to prevent ambiguities when type
// deductions occurs on multiple function-template arguments.  Our sample
// function returns a number within a range two-thirds of the way between the
// start and end of the range.  The types of the arguments determine the type
// of the result.
//
// First, we implement the function using a simple but potentially ambiguous
// interface:
//..
//  template <class NUMTYPE>
//  inline NUMTYPE twoThirdsOfTheWay1(NUMTYPE first, NUMTYPE last)
//  {
//      return first + (last - first) * 2 / 3;
//  }
//..
// Now, try to invoke our function.  We get into trouble when the two arguments
// have different types; the compiler is unable to deduce a single 'NUMTYPE':
//..
//  int i1 = twoThirdsOfTheWay1(0, 6);        // OK, 'NUMTYPE' is 'int'
//  double d1 = twoThirdsOfTheWay1(0, 0.75);  // Ambiguous: 'int' vs 'double'
//..
// Next, we try again, this time using 'bsl::type_identity' to suppress type
// deduction on the first argument.  The *first* argument, rather than the
// *second* argument is chosen for this treatment because the first argument of
// a numeric range is so often 0, which happens to be an 'int' but is often
// used, without losing precision, with 'unsigned', 'float', and 'double'
// values.  The second argument, conversely, usually carries a significant
// value whose type is important:
//..
//  template <class NUMTYPE>
//  inline NUMTYPE twoThirdsOfTheWay(BSLMF_TYPEIDENTITY_T(NUMTYPE) first,
//                                   NUMTYPE                       last)
//  {
//      return first + (last - first) * 2 / 3;
//  }
//
//  int i2 = twoThirdsOfTheWay(0, 6);        // OK, 'NUMTYPE' is 'int'
//  double d2 = twoThirdsOfTheWay(0, 0.75);  // OK, 'NUMTYPE' is 'double'
//..
// Finally, we verify that our 'twoThirdsOfTheWay' function worked correctly:
//..
//  int main()
//  {
//      assert(4 == i2);
//      assert(0.5 == d2);
//      assert(0 == twoThirdsOfTheWay(4U, -2));
//  }
//..

#include <bslscm_version.h>

#include <bsls_compilerfeatures.h>

namespace bsl {

                    // ============================
                    // class template type_identity
                    // ============================

template <class t_TYPE>
struct type_identity {
    // Metafunction returning 't_TYPE' unchanged.

    // TYPES
    typedef t_TYPE type;
};

                    // ==============================
                    // alias template type_identity_t
                    // ==============================

#ifdef BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES

template <class t_TYPE>
using type_identity_t = typename type_identity<t_TYPE>::type;
    // Metafunction returning 't_TYPE' unchanged.  Shorthand alias for
    // 'type_identity<t_TYPE>::type'.

#endif // BSLS_COMPILERFEATURES_SUPPORT_ALIAS_TEMPLATES

}  // close namespace bsl

                    // ==========================
                    // macro BSLMF_TYPEIDENTITY_T
                    // ==========================

#define BSLMF_TYPEIDENTITY_T(...) \
    typename ::bsl::type_identity<__VA_ARGS__ >::type
    // Metafunction returning its type argument unchanged.  Shorthand alias for
    // 'typename type_identity<...>::type'.  The type argument to this macro
    // must be a *dependent type* of the function template or class template in
    // which it is used, i.e., a template parameter or type related to a
    // template parameter.  Note that this macro exists for compatibility with
    // C++03; for C++11 and later compilers, 'bsl::type_identity_t' is
    // preferred.
    //
    // Implementation note: space before closing '>' is important to avoid
    // '>>' issues in C++03.

#endif // ! defined(INCLUDED_BSLMF_TYPEIDENTITY)

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