//#####################################################################
// Copyright 2003-2007, Geoffrey Irving, Frank Losasso, Neil Molino.
// This file is part of PhysBAM whose distribution is governed by the license contained in the accompanying file PHYSBAM_COPYRIGHT.txt.
//#####################################################################
// Class TUPLE
//##################################################################### 
#ifndef __TUPLE__
#define __TUPLE__

#include <Core/Data_Structures/HASH_REDUCE.h>
#include <iostream>
#include <tuple>
#include <utility>
using std::tuple;
using std::get;
using std::pair;
namespace PhysBAM{

void Ignore(std::istream& input,char c);

template<class T1,class T2> inline std::ostream&
operator<<(std::ostream& output,const pair<T1,T2>& p);

template<typename... Args>
std::ostream& operator<<(std::ostream& out,const std::tuple<Args...>& t)
{
    out << '(';
    std::apply(
        [&out](const Args&... args)
        {
            std::size_t n=0;
            ((out << args << (++n != sizeof...(Args) ? " " : "")), ...);
        }, t);
    out << ')';
    return out;
}

template<class... Args> struct HASH_REDUCE<tuple<Args...> >
{
    static int H(const tuple<Args...>& key)
    {return std::apply([](const Args&... args){return int_hash(HASH_REDUCE<Args>::H(args)...);},key);}
};

template<class T1,class T2>
inline std::istream& operator>>(std::istream& input,pair<T1,T2>& p)
{Ignore(input,'(');input>>p.first>>p.second;Ignore(input,')');return input;}

template<typename... Args>
inline std::istream& operator>>(std::istream& input,std::tuple<Args...>& t)
{
    std::apply([&input](Args&... args) {((input >> args), ...);}, t);
    return input;
}

template<class T1,class T2>
inline std::ostream&
operator<<(std::ostream& output,const pair<T1,T2>& p)
{output<<"("<<p.first<<" "<<p.second<<")";return output;}
template<class T1,class T2> struct HASH_REDUCE<pair<T1,T2> >
{static int H(const pair<T1,T2>& key){return int_hash(HASH_REDUCE<T1>::H(key.first),HASH_REDUCE<T2>::H(key.second));}};

}
#endif
