#include <iostream>
#include <string>
#include <tuple>
using namespace std;
/*********************************************************************
* Implementation for utility function "PrintEachInTuple" begin here
*/
namespace detail
{
template<int... Is>
struct seq { };
template<int N, int... Is>
struct gen_seq : gen_seq<N-1, N-1, Is...> { };
template<int... Is>
struct gen_seq<0, Is...> : seq<Is...> { };
template<typename T, typename F, int... Is>
void for_each(T&& t, F f, seq<Is...>)
{
auto l = { (f(std::get<Is>(t)), 0)... };
}
}
template<typename... Ts, typename F>
void PrintEachInTuple(std::tuple<Ts...> const& t, F f)
{
detail::for_each(t, f, detail::gen_seq<sizeof...(Ts)>());
}
struct print_functor
{
template<typename T>
void operator () ( T&& t)
{
t.Print();
}
};
/*
* Implementation for utility function "PrintEachInTuple" ends here
********************************************************************/
class DocumentStreamFactory;
/* Main class for writing stuff with. Only preamble writing implemented, yet */
template<typename... Types>
class DocumentStream
{
private:
DocumentStream(Types... args)
{
tuple<Types...> t(args...);
PrintEachInTuple(t, print_functor());
}
friend class DocumentStreamFactory;
};
/* Factory for DocumentStream objects */
class DocumentStreamFactory
{
public:
template<typename... Types>
static DocumentStream<Types...> Create(Types... args)
{
return DocumentStream<Types...>(args...);
}
class PreambleElement
{
void Print();
};
class Title : public PreambleElement
{
public:
Title() {};
Title(const std::string& title) : title(title) {};
void Print() const { std::cout << "\\title{\"" << title << "\"}" << endl; }
private:
std::string title;
};
class Author : public PreambleElement
{
public:
Author() {};
Author(const std::string& author) : author(author) {};
void Print() const { std::cout << "\\author{\"" << author << "\"}" << endl; }
private:
std::string author;
};
class Date : public PreambleElement
{
public:
Date() {};
Date(int day, int month, int year) : day(day), month(month), year(year) {};
static Date Today() { return Date(22, 1, 2014); } // TODO
void Print() const { std::cout << "\\date{\"" << day << ". " << month << ". " << year << "\"}" << endl; }
private:
int day, month, year;
};
};
int main()
{
cout << "Preamble with title, author and date:" << endl;
auto doc = DocumentStreamFactory::Create(DocumentStreamFactory::Title("Such title name"),
DocumentStreamFactory::Author("Author name"),
DocumentStreamFactory::Date::Today());
cout << endl;
cout << "Preamble with title and date:" << endl;
auto doc_without_author = DocumentStreamFactory::Create(DocumentStreamFactory::Title("Such title name"),
DocumentStreamFactory::Date::Today());
return 0;
}