//OriginalSource:
//  https://github.com/pdimov/variant2/blob/develop/test/variant_visit.cpp
//Purpose:
//  Provide overloads to make more realistic visit test.
//======================
// Copyright 2017 Peter Dimov.
//
// 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

#include <boost/variant2/variant.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/core/lightweight_test_trait.hpp>
#include <boost/config.hpp>
#include <iostream>

template<unsigned I>
struct unsigned_i
{
  unsigned_i(unsigned i=I)
  : value(i)
  {}
  unsigned value;
};

using namespace boost::variant2;

struct overload4
{
    template
    < unsigned I1
    , unsigned I2
    , unsigned I3
    , unsigned I4
    >
    void 
  operator()
    ( unsigned_i<I1>
    , unsigned_i<I2>
    , unsigned_i<I3>
    , unsigned_i<I4>
    )const
    {
      std::cout<<"overload4::general.\n";
      std::cout<<"arg1:unsigned_i<"<<I1<<">.\n";
      std::cout<<"arg2:unsigned_i<"<<I2<<">.\n";
      std::cout<<"arg3:unsigned_i<"<<I3<<">.\n";
      std::cout<<"arg3:unsigned_i<"<<I4<<">.\n";
    }
    template
    < unsigned I1
    , unsigned I2
    , unsigned I3
    >
    void 
  operator()
    ( unsigned_i<I1>
    , unsigned_i<I2>
    , unsigned_i<I3>
    , unsigned_i<4>
    )const
    {
      std::cout<<"overload4::specialized on arg4:unsigned_i<4>.\n";
      std::cout<<"arg1:unsigned_i<"<<I1<<">.\n";
      std::cout<<"arg2:unsigned_i<"<<I2<<">.\n";
      std::cout<<"arg3:unsigned_i<"<<I3<<">.\n";
    }
};

int main()
{
  #define UNSIGNED_I4
  #ifdef UNSIGNED_I4
    {
        std::cout<<"***UNSIGNED_I4.\n";
          using 
        vt=
          variant
          < unsigned_i<1>
          , unsigned_i<2>
          , unsigned_i<3>
          , unsigned_i<4>
          >
          ;
        vt v1( unsigned_i<1>{} );
        vt v2( unsigned_i<2>{} );
        vt v3( unsigned_i<3>{} );
        vt v4( unsigned_i<4>{} );
        
        visit( overload4{}, v1, v2, v3, v4 );
        visit( overload4{}, v4, v3, v2, v4 );
        visit( overload4{}, v4, v3, v2, v1 );
    }
  #endif
  //#define UNSIGNED_I5
  #ifdef UNSIGNED_I5
    {
        std::cout<<"***UNSIGNED_I5.\n";
          using 
        vt=
          variant
          < unsigned_i<1>
          , unsigned_i<2>
          , unsigned_i<3>
          >
          ;
        vt v1( unsigned_i<1>{} );
        vt v2( unsigned_i<2>{} );
        vt v3( unsigned_i<3>{} );
        vt v4( unsigned_i<1>{} );
        vt v5( unsigned_i<2>{} );

        visit( []( auto x1, auto x2, auto x3, auto x4, auto x5){}, v1, v2, v3, v4, v5 );
    }
  #endif
  //#define UNSIGNED_I6
  #ifdef UNSIGNED_I6
    {
        std::cout<<"***UNSIGNED_I6.\n";
          using 
        vt=
          variant
          < unsigned_i<1>
          , unsigned_i<2>
          , unsigned_i<3>
          >
          ;
        vt v1( unsigned_i<1>{} );
        vt v2( unsigned_i<2>{} );
        vt v3( unsigned_i<3>{} );
        vt v4( unsigned_i<1>{} );
        vt v5( unsigned_i<2>{} );
        vt v6( unsigned_i<3>{} );

        visit( []( auto x1, auto x2, auto x3, auto x4, auto x5, auto x6){}, v1, v2, v3, v4, v5, v6 );
    }
  #endif
    return boost::report_errors();
}

