///\file 
///Named template study

///\e

///\e
///
class AlgorithmDefaultTypes 
{
public:
///\e

///\e
///
  typedef int Adat;
};

///\e

///\e
///
template<class T = AlgorithmDefaultTypes>
class AlgorithmTypes : public T 
{
public:
///\e

///\e
///
  template<class X>
  class SetAdat : public T { X Adat; };
};

///\e

///\e
///
template<class T = AlgorithmTypes<> >
class AlgorithmDefaultDataFields : public T
{
protected:
///\e

///\e
///
  typedef T TypeTraits; //Jo ez a nev?
protected:
///\e

///\e
///
  typename T::Adat adat;
};

///\e

///\e
///
template<class T = AlgorithmDefaultDataFields<> >
class Algorithm : public T
{
  int _intAdat;
public:
  Algorithm() {};
  Algorithm(const T &tt) : T(tt) {};

  template<class X> class _SetAdat : public T {
    protected:
    X adat;
    public:
    typedef X Adat;
    _SetAdat() {}; //"Algorithm<>::_SetAdat<double> b;"-hez kell!!!!
                   // De az is rossz!!!!!
    _SetAdat(const T &t,const X& x) : T(t), adat(x) {};
  };
  
 ///\name Funtion Named Parameters
  
  ///@{

  ///\e
  
  ///\e
  ///
  template<class X>
  Algorithm<_SetAdat<X> > setAdat(const X &x) {
    return Algorithm<_SetAdat<X> >(_SetAdat<X>(*this,x));
  }

  ///@}
  ///\name Named Parameters
  
  ///@{

  ///\e
  
  ///\e
  ///
  template<class X>
  class SetAdat :
    public Algorithm<AlgorithmDefaultDataFields<
    typename T::TypeTraits::template SetAdat<X> > >
  {};
  
  ///@}  

///\e

///\e
///
  Algorithm &setIntAdat(int i) {_intAdat=i;return *this;}
  //vagy:
///Vagy

///Vagy...
///
  Algorithm &intAdat(int i) {_intAdat=i;return *this;}
  
  //Maga az algoritmus!!!!!!!
///\e

///\e
///
  typename T::Adat run()
  {
    //Itt csinalunk valamit
    return adat;    
  }

  ~Algorithm()
  {
    //Itt nem csinalunk semmit
  }
};

///\e

///\e
///
Algorithm<> algorithm() 
{
  return Algorithm<>();
}

int main() 
{
  Algorithm<> a;
  a.run();

//   Algorithm<>::_SetAdat<double> b; b=b;//Ez itt nem az, amit szeretnenk!!! 
//   //  b.run();
  
  Algorithm<>::SetAdat<double> c; //Algorithm<>::Adat<double> c; jobb vo'na
  c.run();

  algorithm().run();
  algorithm().setAdat(5.2).run();
}
