text:
#include <boost/ut.hpp>
#include <libembeddedhal/serial/util.hpp>
#include <span>

namespace embed {
boost::ut::suite serial_util_test = []() {
  using namespace boost::ut;
  using namespace std::chrono_literals;

  // static constexpr std::byte success_filler{ 0xF5 };
  static constexpr std::byte write_failure_byte{ 0x33 };
  static constexpr std::byte filler_byte{ 0xA5 };

  class dummy : public embed::serial
  {
  public:
    [[nodiscard]] boost::leaf::result<void> driver_configure(
      const settings&) noexcept override
    {
      return {};
    }
    [[nodiscard]] boost::leaf::result<void> driver_write(
      std::span<const std::byte> p_data) noexcept override
    {
      if (p_data[0] == write_failure_byte) {
        return boost::leaf::new_error();
      }
      m_out = p_data;
      return {};
    }

    [[nodiscard]] boost::leaf::result<size_t> driver_bytes_available() noexcept
      override
    {
      if (m_bytes_available_fails) {
        return boost::leaf::new_error();
      }
      return ++m_bytes_available;
    }

    [[nodiscard]] boost::leaf::result<std::span<const std::byte>> driver_read(
      std::span<std::byte> p_data) noexcept override
    {
      if (m_read_fails) {
        return boost::leaf::new_error();
      }
      m_in = p_data;
      std::fill(p_data.begin(), p_data.end(), filler_byte);
      return p_data;
    }

    [[nodiscard]] boost::leaf::result<void> driver_flush() noexcept override
    {
      m_flush_called = true;
      return {};
    }

    virtual ~dummy() {}

    std::span<const std::byte> m_out{};
    std::span<std::byte> m_in{};
    size_t m_bytes_available = 0;
    bool m_flush_called = false;
    bool m_bytes_available_fails = false;
    bool m_read_fails = false;
  };

  "[success] write"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};

    // Exercise
    auto result = write(serial, expected_payload);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(successful);
    expect(!serial.m_flush_called);
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[failure] write"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{ write_failure_byte };

    // Exercise
    auto result = write(serial, expected_payload);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[success] read"_test = []() {
    // Setup
    dummy serial;
    std::array<std::byte, 4> expected_buffer;

    // Exercise
    auto result = read(serial, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % expected_buffer.data() == serial.m_in.data());
    expect(that % expected_buffer.size() == serial.m_in.size());
    expect(that % 4 == serial.m_bytes_available);
  };

  "[failure bytes_available] read"_test = []() {
    // Setup
    dummy serial;
    std::array<std::byte, 4> expected_buffer;
    serial.m_bytes_available_fails = true;

    // Exercise
    auto result = read(serial, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[failure read] read"_test = []() {
    // Setup
    dummy serial;
    std::array<std::byte, 4> expected_buffer;
    serial.m_read_fails = true;

    // Exercise
    auto result = read(serial, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % 4 == serial.m_bytes_available);
  };

  "[success] read<Length>"_test = []() {
    // Setup
    dummy serial;
    std::array<std::byte, 5> expected_buffer;
    expected_buffer.fill(filler_byte);

    // Exercise
    auto result = read<expected_buffer.size()>(serial);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(successful);
    expect(!serial.m_flush_called);
    expect(std::equal(
      expected_buffer.begin(), expected_buffer.end(), result.value().begin()));
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
  };

  "[failure bytes_available] read<Length>"_test = []() {
    // Setup
    dummy serial;
    serial.m_bytes_available_fails = true;

    // Exercise
    auto result = read<5>(serial);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[failure read] read<Length>"_test = []() {
    // Setup
    dummy serial;
    serial.m_read_fails = true;

    // Exercise
    auto result = read<5>(serial);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % 5 == serial.m_bytes_available);
  };

  "[success] write_then_read"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};
    std::array<std::byte, 4> expected_buffer;

    // Exercise
    auto result = write_then_read(serial, expected_payload, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(successful);
    expect(!serial.m_flush_called);
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(that % expected_buffer.data() == serial.m_in.data());
    expect(that % expected_buffer.size() == serial.m_in.size());
  };

  "[failure bytes_available] write_then_read"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};
    std::array<std::byte, 4> expected_buffer;
    expected_buffer.fill(filler_byte);
    serial.m_bytes_available_fails = true;

    // Exercise
    auto result = write_then_read(serial, expected_payload, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[failure read] write_then_read"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};
    std::array<std::byte, 4> expected_buffer;
    expected_buffer.fill(filler_byte);
    serial.m_read_fails = true;

    // Exercise
    auto result = write_then_read(serial, expected_payload, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(that % 4 == serial.m_bytes_available);
  };

  "[failure on write] write_then_read"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{ write_failure_byte };
    std::array<std::byte, 4> expected_buffer;

    // Exercise
    auto result = write_then_read(serial, expected_payload, expected_buffer);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[success] write_then_read<Length>"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};
    std::array<std::byte, 4> expected_buffer{};
    expected_buffer.fill(filler_byte);

    // Exercise
    auto result = write_then_read<5>(serial, expected_payload);
    bool successful = static_cast<bool>(result);
    auto actual_array = result.value();

    // Verify
    expect(successful);
    expect(!serial.m_flush_called);
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(std::equal(
      expected_buffer.begin(), expected_buffer.end(), actual_array.begin()));
  };

  "[failure on write] write_then_read<Length>"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{ write_failure_byte };

    // Exercise
    auto result = write_then_read<5>(serial, expected_payload);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % nullptr == serial.m_out.data());
    expect(that % 0 == serial.m_out.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[failure bytes_available] write_then_read<Length>"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};
    serial.m_bytes_available_fails = true;

    // Exercise
    auto result = write_then_read<5>(serial, expected_payload);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(that % 0 == serial.m_bytes_available);
  };

  "[failure read] write_then_read<Length>"_test = []() {
    // Setup
    dummy serial;
    const std::array<std::byte, 4> expected_payload{};
    serial.m_read_fails = true;

    // Exercise
    auto result = write_then_read<5>(serial, expected_payload);
    bool successful = static_cast<bool>(result);

    // Verify
    expect(!successful);
    expect(!serial.m_flush_called);
    expect(that % nullptr == serial.m_in.data());
    expect(that % 0 == serial.m_in.size());
    expect(that % expected_payload.data() == serial.m_out.data());
    expect(that % expected_payload.size() == serial.m_out.size());
    expect(that % 5 == serial.m_bytes_available);
  };
};
}  // namespace embed

max_stars_repo_name: MaliaLabor/libembeddedhal

max_issues_repo_name: MaliaLabor/libembeddedhal

max_forks_repo_name: MaliaLabor/libembeddedhal


text:
//  Copyright (c) 2013 Hartmut Kaiser
//  Copyright (c) 2017 Denis Blank
//
//  SPDX-License-Identifier: BSL-1.0
//  Distributed under the Boost Software License, Version 1.0. (See accompanying
//  file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)

#define HPX_NO_VERSION_CHECK

#include <hpx/assertion.hpp>
#include <hpx/testing.hpp>

#include <cstddef>
#include <cstdint>
#include <functional>
#include <iostream>
#include <sstream>

#include <boost/io/ios_state.hpp>

namespace hpx { namespace util {
    static test_failure_handler_type test_failure_handler;

    void set_test_failure_handler(test_failure_handler_type f)
    {
        test_failure_handler = f;
    }

    namespace detail {
        void fixture::increment(counter_type c)
        {
            if (test_failure_handler)
            {
                test_failure_handler();
            }

            switch (c)
            {
            case counter_sanity:
                ++sanity_failures_;
                return;
            case counter_test:
                ++test_failures_;
                return;
            default:
                break;
            }
            HPX_ASSERT(false);
        }

        std::size_t fixture::get(counter_type c) const
        {
            switch (c)
            {
            case counter_sanity:
                return sanity_failures_;
            case counter_test:
                return test_failures_;
            default:
                break;
            }
            HPX_ASSERT(false);
            return std::size_t(-1);
        }

        fixture global_fixture{std::cerr};
    }    // namespace detail

    ////////////////////////////////////////////////////////////////////////////
    int report_errors(std::ostream& stream)
    {
        std::size_t sanity = detail::global_fixture.get(counter_sanity),
                    test = detail::global_fixture.get(counter_test);
        if (sanity == 0 && test == 0)
            return 0;

        else
        {
            boost::io::ios_flags_saver ifs(stream);
            stream << sanity << " sanity check"    //-V128
                   << ((sanity == 1) ? " and " : "s and ") << test << " test"
                   << ((test == 1) ? " failed." : "s failed.") << std::endl;
            return 1;
        }
    }

    void print_cdash_timing(const char* name, double time)
    {
        // use stringstream followed by single cout for better multi-threaded
        // output
        std::stringstream temp;
        temp << "<DartMeasurement name=\"" << name << "\" "
             << "type=\"numeric/double\">" << time << "</DartMeasurement>";
        std::cout << temp.str() << std::endl;
    }

    void print_cdash_timing(const char* name, std::uint64_t time)
    {
        print_cdash_timing(name, time / 1e9);
    }
}}    // namespace hpx::util

ext: cpp

max_stars_repo_name: jnvance/hpx

max_issues_repo_name: jnvance/hpx

max_forks_repo_name: jnvance/hpx


text:
/* CirKit: A circuit toolkit
 * Copyright (C) 2009-2015  University of Bremen
 * Copyright (C) 2015-2017  EPFL
 *
 * Permission is hereby granted, free of charge, to any person
 * obtaining a copy of this software and associated documentation
 * files (the "Software"), to deal in the Software without
 * restriction, including without limitation the rights to use,
 * copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the
 * Software is furnished to do so, subject to the following
 * conditions:
 *
 * The above copyright notice and this permission notice shall be
 * included in all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
 * OTHER DEALINGS IN THE SOFTWARE.
 */

#include "write_liquid.hpp"

#include <fstream>
#include <vector>

#include <boost/algorithm/string/join.hpp>
#include <boost/format.hpp>

#include <core/utils/string_template.hpp>
#include <reversible/target_tags.hpp>

namespace cirkit
{

/******************************************************************************
 * Types                                                                      *
 ******************************************************************************/

/******************************************************************************
 * Private functions                                                          *
 ******************************************************************************/

void write_liquid( const circuit& circ, std::ostream& os, const properties::ptr& settings )
{
  const auto dump_statement = get( settings, "dump_statement", false );

  string_template t(
    "#if INTERACTIVE\n"
    "#r @\"..\\bin\\Liquid1.dll\"\n"
    "#else\n"
    "namespace Microsoft.Research.Liquid\n"
    "#endif\n\n"
    "open System\n\n"
    "open Microsoft.Research.Liquid\n"
    "open Util\n"
    "open Operations\n\n"
    "module Script =\n"
    "    [<LQD>]\n"
    "    let RevKit() =\n"
    "        let MPMCT(qs: Qubits)(negcs: Qubits) =\n"
    "            let nc = qs.Length - 1           // number of controls\n"
    "            let cs = List.replicate nc Cgate // control lines\n"
    "            let cg = List.fold (<<) id cs    // make controlled operation\n"
    "            for n in negcs do X [n]          // negative controls\n"
    "            cg X qs                          // apply gate\n"
    "            for n in negcs do X [n]          // negative controls\n\n"
    "        let ops(qs: Qubits) =\n"
    "{{ gates }}\n"
    "        let ket  = Ket({{ lines }})\n"
    "        let qs   = ket.Qubits\n"
    "        let circ = ( Circuit.Compile ops qs ).GrowGates( ket )\n\n"
    "        show \"#gates in grown circuit: %d\" (circ.GateCount())\n{{ dump }}\n"
    "#if INTERACTIVE\n"
    "do Script.RevKit()\n"
    "#endif\n" );

  std::string gstrs;
  for ( const auto& g : circ )
  {
    assert( is_toffoli( g ) );

    std::string gstr = "          MPMCT [";
    std::vector<std::string> neg;

    for ( const auto& c : g.controls() )
    {
      gstr += boost::str( boost::format( "qs.[%d];" ) % c.line() );

      if ( !c.polarity() )
      {
        neg.push_back( boost::str( boost::format( "qs.[%d]" ) % c.line() ) );
      }
    }
    gstr += boost::str( boost::format( "qs.[%d]] [%s]\n" ) % g.targets().front() % boost::join( neg, ";" ) );

    gstrs += gstr;
  }

  std::string dump;
  if ( dump_statement )
  {
    dump = "        circ.Dump()\n";
  }

  os << t( std::unordered_map<std::string, std::string>( {
        {"gates", gstrs},
        {"lines", std::to_string( circ.lines() )},
        {"dump", dump}
      } ) );
}

/******************************************************************************
 * Public functions                                                           *
 ******************************************************************************/

void write_liquid( const circuit& circ, const std::string& filename, const properties::ptr& settings )
{
  std::ofstream os( filename.c_str(), std::ofstream::out );
  write_liquid( circ, os, settings );
  os.close();
}

}

// Local Variables:
// c-basic-offset: 2
// eval: (c-set-offset 'substatement-open 0)
// eval: (c-set-offset 'innamespace 0)
// End:

max_stars_repo_name: eletesta/cirkit

max_issues_repo_name: eletesta/cirkit

max_forks_repo_name: eletesta/cirkit


text:
//-----------------------------------------------------------------------------
// boost variant/recursive_wrapper_fwd.hpp header file
// See http://www.boost.org for updates, documentation, and revision history.
//-----------------------------------------------------------------------------
//
// Copyright (c) 2002
// Eric Friedman, Itay Maman
//
// Portions Copyright (C) 2002 David Abrahams
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)

#ifndef BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP
#define BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP

#include <boost/mpl/bool.hpp>
#include "boost/mpl/aux_/config/ctps.hpp"
#include "boost/mpl/aux_/lambda_support.hpp"
#include <boost/type_traits/integral_constant.hpp>

namespace boost {

//////////////////////////////////////////////////////////////////////////
// class template recursive_wrapper
//
// Enables recursive types in templates by breaking cyclic dependencies.
//
// For example:
//
//   class my;
//
//   typedef variant< int, recursive_wrapper<my> > var;
//
//   class my {
//     var var_;
//     ...
//   };
//
template <typename T> class recursive_wrapper;

///////////////////////////////////////////////////////////////////////////////
// metafunction is_recursive_wrapper (modeled on code by David Abrahams)
//
// True iff specified type matches recursive_wrapper<T>.
//

namespace detail {

template <typename T>
struct is_recursive_wrapper_impl
    : mpl::false_
{
};

template <typename T>
struct is_recursive_wrapper_impl< recursive_wrapper<T> >
    : mpl::true_
{
};

} // namespace detail

template< typename T > struct is_recursive_wrapper
    : public ::boost::integral_constant<bool,(::boost::detail::is_recursive_wrapper_impl<T>::value)>
{
public:
    BOOST_MPL_AUX_LAMBDA_SUPPORT(1,is_recursive_wrapper,(T))
};

///////////////////////////////////////////////////////////////////////////////
// metafunction unwrap_recursive
//
// If specified type T matches recursive_wrapper<U>, then U; else T.
//

template <typename T>
struct unwrap_recursive
{
    typedef T type;

    BOOST_MPL_AUX_LAMBDA_SUPPORT(1,unwrap_recursive,(T))
};

template <typename T>
struct unwrap_recursive< recursive_wrapper<T> >
{
    typedef T type;

    BOOST_MPL_AUX_LAMBDA_SUPPORT_SPEC(1,unwrap_recursive,(T))
};

} // namespace boost

#endif // BOOST_VARIANT_RECURSIVE_WRAPPER_FWD_HPP

ext: hpp

max_stars_repo_name: mistydew/RSSearch

max_issues_repo_name: mistydew/RSSearch

max_forks_repo_name: mistydew/RSSearch


text:
#include <boost/type_index.hpp>
#include <cstdlib>
#include <iostream>
using namespace std;

//普通函数
void myFunction(int value01, int value02) {
    ++value02;
    cout << "Sum=" << value02 + value01 << endl;
    return;
}

//左值引用
void myFunction02(int value01, int &value02) {
    ++value02;
    cout << "Sum=" << value02 + value01 << endl;
    return;
}

//改为右值引用
void myFunction03(int &&value01, int &value02) {
    ++value02;
    cout << "Sum=" << value02 + value01 << endl;
    return;
}

//模板函数，要把收到的参数以及这些参数相对应的类型保持不变转发为其他函数myFunction  --这就是转发
template <typename F, typename T1, typename T2>
void myFunctionTramsmit(F f, T1 t1, T2 t2) {  // F就是要调用的第三方函数，要转发的目标函数
    f(t1, t2);
}

//将函数模板改为万能引用类型
template <typename F, typename T1, typename T2>
void myFunctionTramsmit02(F f, T1 &&t1, T2 &&t2) {
    /*针对主函数中的调用myFunctionTramsmit02(myFunction02, 34, i);
     *T1=int, t1=int&&  t1是右值引用类型，t1本身是左值
     *T2=int&,t2=int&
     *
     */
    // f(t1, t2);
    //“void(int &&, int &)”: 无法将参数1 从“int”转换为“int &&”
    //调用处的是一个右值，但是通过万能引用转换为一个左值了，t1本身是一个左值，但是函数myFunction03需要的是一个右值
    f(std::forward<T1>(t1), std::forward<T2>(t2));
    // t1中原来是左值还是右值信息存在在T1模板参数中，这里会将t1转换为原始实参的右值类型
}

int main(void) {
    int i = 50;
    myFunction(34, i);

    //通过转发函数调用
    myFunctionTramsmit(myFunction, 34, i);
    myFunctionTramsmit(myFunction02, 34, i);  //这里返回后i=50，并不是我们期望的51。也就是说，T2并没有实例化为int&类型
    // void myFunctionTramsmit(void(*f)(int,int&),int t1,int t2){}//实例化后的样子，t2这个参数并不是真正传递过去引用类型
    //怎么修改传递函数，让模板函数的参数能够保持给定实参的左值性（i有const属性也传递到模板函数中）？？？？
    /*
     *万能引用  T&& 保存实参i的所有属性，从而让编译器推导出来函数模板最终的形参类型
     *如果使用T&普通引用，则实参中只有const属性可以传递到函数模板，而实参中的左值和右值性就不能传递到函数模板
     *
     */

    //万能引用后调用
    myFunctionTramsmit02(myFunction02, 34, i);  // i的值是51

    //右值引用
    int &&number01 = 80;  //右值引用绑定右值
    /*
     * number01的类型是右值引用，但是本身是个左值，在内存中有地址。也就是说左值引用，右值引用概念说的是它的类型。
     * void myFunctionTramsmit02(F f, T1 &&t1, T2 &&t2)函数形参中的变量都是左值，本身类型是右值引用
     */

    myFunction03(number01, i);  //error，形参中是一个右值引用，必须绑定一个右值，number01本质上是一个左值

    int j = 50;
    myFunctionTramsmit02(myFunction03, 20, j);

    system("pause");
    return 0;
}
/*
* (1)转发和完美转发
*	通过函数指针调用函数，并把函数参数作为参数传递，就是转发。
*
*	完美转发：让我们可以写接受任意类型实参的函数模板，并将其转发到目标函数，
*		目标函数会接收到与转发函数所接收到的参数类型完全相同（左值性，右值性）
*		通过std::forword()来实现
*
* (2)std::forward()
*	c++11中的新函数，专门为转发而存在。
*	它要么返回一个左值，要么返回一个右值。
*	使用条件：
*		调用模板函数，模板函数参数是万能引用类型，模板参数负责转发
*		void myFunctionTramsmit02(F f, T1 &&t1, T2 &&t2)
*		f(std::forward<T1>(t1), std::forward<T2>(t2));
*		void myFunction03(int &&value01, int &value02)//value01要绑定一个右值
*		//调用
*		myFunctionTramsmit02(myFunction03, 20, j);
*
*	std::forword()的能力就是按照实参本身的类型转发。
*		1.实参原来是左值，到形参中还是左值，forward是按照形参原来的类型处理，所以std::forward处理后还是左值
*		2.实参原来是右值，到形参中变成左值，forward是按照形参原来的类型处理，所以std::forward处理后是个右值
*		所以这里看来std::forward()有强制把左值转换为右值的能力，所以forward()其实只对原来是右值的情况有用。
*
*		std::forward()的能力就是保持原始实参的类型（左值还是右值）
* (3)完美转发是如何保存原始实参的左值和右值信息？
*	是保存在转发函数（函数模板中）的模板参数T中，所以转发函数的参数类型必须是万能引用类型。
* (4)总结
*   forward()是强制把一个左值转换为右值，如果你的原始形参就是一个左值，那我的forward啥也不干
*   move()无条件强制类型转换，转换后原始对象名字不能使用。
*
* (5)再谈万能引用
*	万能引用不是一种新的引用类型。是一种程序的写法。但是万能引用概念的存在是有意义的。
*
* 1.转发函数
* 2.左值和右值
* 3.完美转发std::forward()
*/

max_stars_repo_path: 9.未归类知识点/06转发函数和完美转发.cpp

max_stars_repo_name: xuesongzh/cpp-basis

max_issues_repo_path: 9.未归类知识点/06转发函数和完美转发.cpp

max_issues_repo_name: xuesongzh/cpp-basis

max_forks_repo_path: 9.未归类知识点/06转发函数和完美转发.cpp

max_forks_repo_name: xuesongzh/cpp-basis