#pragma once
/*
 *  FakeIt - A Simplified C++ Mocking Framework
 *  Copyright (c) Eran Pe'er 2013
 *  Generated: 2018-08-17 00:22:40.428924
 *  Distributed under the MIT License. Please refer to the LICENSE file at:
 *  https://github.com/eranpeer/FakeIt
 */

#ifndef fakeit_h__
#define fakeit_h__


#if defined __GNUC__
#    pragma GCC diagnostic push
#    pragma GCC diagnostic ignored "-Wcast-function-type"
#    pragma GCC diagnostic ignored "-Wsuggest-override"
#endif

#include <functional>
#include <memory>
#include <set>
#include <vector>
#include <stdexcept>
#if defined (__GNUG__) || _MSC_VER >= 1900
#define THROWS noexcept(false)
#define NO_THROWS noexcept(true)
#elif defined (_MSC_VER)
#define THROWS throw(...)
#define NO_THROWS
#endif
#include <typeinfo>
#include <unordered_set>
#include <tuple>
#include <string>
#include <iosfwd>
#include <atomic>
#include <tuple>


namespace fakeit {

    template<class C>
    struct naked_type {
        typedef typename std::remove_cv<typename std::remove_reference<C>::type>::type type;
    };

    template< class T > struct tuple_arg         { typedef T  type; };
    template< class T > struct tuple_arg < T& >  { typedef T& type; };
    template< class T > struct tuple_arg < T&& > { typedef T&&  type; };




    template<typename... arglist>
    using ArgumentsTuple = std::tuple < arglist... > ;

    template< class T > struct test_arg         { typedef T& type; };
    template< class T > struct test_arg< T& >   { typedef T& type; };
    template< class T > struct test_arg< T&& >  { typedef T& type; };

    template< class T > struct production_arg         { typedef T& type; };
    template< class T > struct production_arg< T& >   { typedef T& type; };
    template< class T > struct production_arg< T&& >  { typedef T&&  type; };

    template <typename T>
    class is_ostreamable {
        struct no {};
#if defined(_MSC_VER) && _MSC_VER < 1900
        template <typename T1>
        static decltype(operator<<(std::declval<std::ostream&>(), std::declval<const T1>())) test(std::ostream &s, const T1 &t);
#else
        template <typename T1>
        static auto test(std::ostream &s, const T1 &t) -> decltype(s << t);
#endif
        static no test(...);
    public:

        static const bool value =
            std::is_arithmetic<T>::value ||
            std::is_pointer<T>::value ||
            std::is_same<decltype(test(*(std::ostream *)nullptr,
                std::declval<T>())), std::ostream &>::value;
    };


    template <>
    class is_ostreamable<std::ios_base& (*)(std::ios_base&)> {
    public:
        static const bool value = true;
    };

    template <typename CharT, typename Traits>
    class is_ostreamable<std::basic_ios<CharT,Traits>& (*)(std::basic_ios<CharT,Traits>&)> {
    public:
        static const bool value = true;
    };

    template <typename CharT, typename Traits>
    class is_ostreamable<std::basic_ostream<CharT,Traits>& (*)(std::basic_ostream<CharT,Traits>&)> {
    public:
        static const bool value = true;
    };

    template<typename R, typename... arglist>
    struct VTableMethodType {
#if defined (__GNUG__)
        typedef R(*type)(void *, arglist...);
#elif defined (_MSC_VER)
        typedef R(__thiscall *type)(void *, arglist...);
#endif
    };
}
#include <typeinfo>
#include <tuple>
#include <string>
#include <iosfwd>
#include <sstream>
#include <string>

namespace fakeit {

    struct FakeitContext;

    template<typename C>
    struct MockObject {
        virtual ~MockObject() THROWS { };

        virtual C &get() = 0;

        virtual FakeitContext &getFakeIt() = 0;
    };

    struct MethodInfo {

        static unsigned int nextMethodOrdinal() {
            static std::atomic_uint ordinal{0};
            return ++ordinal;
        }

        MethodInfo(unsigned int anId, std::string aName) :
                _id(anId), _name(aName) { }

        unsigned int id() const {
            return _id;
        }

        std::string name() const {
            return _name;
        }

        void setName(const std::string &value) {
            _name = value;
        }

    private:
        unsigned int _id;
        std::string _name;
    };

    struct UnknownMethod {

        static MethodInfo &instance() {
            static MethodInfo instance(MethodInfo::nextMethodOrdinal(), "unknown");
            return instance;
        }

    };

}
namespace fakeit {
    class Destructible {
    public:
        virtual ~Destructible() {}
    };
}

namespace fakeit {

    struct Invocation : Destructible {

        static unsigned int nextInvocationOrdinal() {
            static std::atomic_uint invocationOrdinal{0};
            return ++invocationOrdinal;
        }

        struct Matcher {

            virtual ~Matcher() THROWS {
            }

            virtual bool matches(Invocation &invocation) = 0;

            virtual std::string format() const = 0;
        };

        Invocation(unsigned int ordinal, MethodInfo &method) :
                _ordinal(ordinal), _method(method), _isVerified(false) {
        }

        virtual ~Invocation() override = default;

        unsigned int getOrdinal() const {
            return _ordinal;
        }

        MethodInfo &getMethod() const {
            return _method;
        }

        void markAsVerified() {
            _isVerified = true;
        }

        bool isVerified() const {
            return _isVerified;
        }

        virtual std::string format() const = 0;

    private:
        const unsigned int _ordinal;
        MethodInfo &_method;
        bool _isVerified;
    };

}
#include <iosfwd>
#include <tuple>
#include <string>
#include <sstream>
#include <ostream>

namespace fakeit {

	template<typename T, class Enable = void>
	struct Formatter;

	template <>
	struct Formatter<bool>
	{
		static std::string format(bool const &val)
		{
			return val ? "true" : "false";
		}
	};

	template <>
	struct Formatter<char>
	{
		static std::string format(char const &val)
		{
			std::string s;
			s += "'";
			s += val;
			s += "'";
			return s;
		}
	};

	template <>
	struct Formatter<char const*>
	{
		static std::string format(char const* const &val)
		{
			std::string s;
			if(val != nullptr)
			{
				s += '"';
				s += val;
				s += '"';
			}
			else
			{
				s = "[nullptr]";
			}
			return s;
		}
	};

	template <>
	struct Formatter<char*>
	{
		static std::string format(char* const &val)
		{
			return Formatter<char const*>::format( val );
		}
	};

	template<class C>
	struct Formatter<C, typename std::enable_if<!is_ostreamable<C>::value>::type> {
		static std::string format(C const &)
		{
			return "?";
		}
	};

	template<class C>
	struct Formatter<C, typename std::enable_if<is_ostreamable<C>::value>::type> {
		static std::string format(C const &val)
		{
			std::ostringstream os;
			os << val;
			return os.str();
		}
	};


	template <typename T>
	using TypeFormatter = Formatter<typename fakeit::naked_type<T>::type>;
}

namespace fakeit {


    template<class Tuple, std::size_t N>
    struct TuplePrinter {
        static void print(std::ostream &strm, const Tuple &t) {
            TuplePrinter<Tuple, N - 1>::print(strm, t);
            strm << ", " << fakeit::TypeFormatter<decltype(std::get<N - 1>(t))>::format(std::get<N - 1>(t));
        }
    };

    template<class Tuple>
    struct TuplePrinter<Tuple, 1> {
        static void print(std::ostream &strm, const Tuple &t) {
            strm << fakeit::TypeFormatter<decltype(std::get<0>(t))>::format(std::get<0>(t));
        }
    };

    template<class Tuple>
    struct TuplePrinter<Tuple, 0> {
        static void print(std::ostream &, const Tuple &) {
        }
    };

    template<class ... Args>
    void print(std::ostream &strm, const std::tuple<Args...> &t) {
        strm << "(";
        TuplePrinter<decltype(t), sizeof...(Args)>::print(strm, t);
        strm << ")";
    }

    template<class ... Args>
    std::ostream &operator<<(std::ostream &strm, const std::tuple<Args...> &t) {
        print(strm, t);
        return strm;
    }

}


namespace fakeit {

    template<typename ... arglist>
    struct ActualInvocation : public Invocation {

        struct Matcher : public virtual Destructible {
            virtual bool matches(ActualInvocation<arglist...> &actualInvocation) = 0;

            virtual std::string format() const = 0;
        };

        ActualInvocation(unsigned int ordinal, MethodInfo &method, const typename fakeit::production_arg<arglist>::type... args) :
            Invocation(ordinal, method), _matcher{ nullptr }
            , actualArguments{ std::forward<arglist>(args)... }
        {
        }

        ArgumentsTuple<arglist...> & getActualArguments() {
            return actualArguments;
        }


        void setActualMatcher(Matcher *matcher) {
            this->_matcher = matcher;
        }

        Matcher *getActualMatcher() {
            return _matcher;
        }

        virtual std::string format() const override {
            std::ostringstream out;
            out << getMethod().name();
            print(out, actualArguments);
            return out.str();
        }

    private:

        Matcher *_matcher;
        ArgumentsTuple<arglist...> actualArguments;
    };

    template<typename ... arglist>
    std::ostream &operator<<(std::ostream &strm, const ActualInvocation<arglist...> &ai) {
        strm << ai.format();
        return strm;
    }

}





#include <unordered_set>

namespace fakeit {

	struct ActualInvocationsContainer {
		virtual void clear() = 0;

		virtual ~ActualInvocationsContainer() NO_THROWS { }
	};

    struct ActualInvocationsSource {
        virtual void getActualInvocations(std::unordered_set<fakeit::Invocation *> &into) const = 0;

        virtual ~ActualInvocationsSource() NO_THROWS { }
    };

    struct InvocationsSourceProxy : public ActualInvocationsSource {

        InvocationsSourceProxy(ActualInvocationsSource *inner) :
                _inner(inner) {
        }

        void getActualInvocations(std::unordered_set<fakeit::Invocation *> &into) const override {
            _inner->getActualInvocations(into);
        }

    private:
        std::shared_ptr<ActualInvocationsSource> _inner;
    };

    struct UnverifiedInvocationsSource : public ActualInvocationsSource {

        UnverifiedInvocationsSource(InvocationsSourceProxy decorated) : _decorated(decorated) {
        }

        void getActualInvocations(std::unordered_set<fakeit::Invocation *> &into) const override {
            std::unordered_set<fakeit::Invocation *> all;
            _decorated.getActualInvocations(all);
            for (fakeit::Invocation *i : all) {
                if (!i->isVerified()) {
                    into.insert(i);
                }
            }
        }

    private:
        InvocationsSourceProxy _decorated;
    };

    struct AggregateInvocationsSource : public ActualInvocationsSource {

        AggregateInvocationsSource(std::vector<ActualInvocationsSource *> &sources) : _sources(sources) {
        }

        void getActualInvocations(std::unordered_set<fakeit::Invocation *> &into) const override {
            std::unordered_set<fakeit::Invocation *> tmp;
            for (ActualInvocationsSource *source : _sources) {
                source->getActualInvocations(tmp);
            }
            filter(tmp, into);
        }

    protected:
        bool shouldInclude(fakeit::Invocation *) const {
            return true;
        }

    private:
        std::vector<ActualInvocationsSource *> _sources;

        void filter(std::unordered_set<Invocation *> &source, std::unordered_set<Invocation *> &target) const {
            for (Invocation *i:source) {
                if (shouldInclude(i)) {
                    target.insert(i);
                }
            }
        }
    };
}

namespace fakeit {

    class Sequence {
    private:

    protected:

        Sequence() {
        }

        virtual ~Sequence() THROWS {
        }

    public:


        virtual void getExpectedSequence(std::vector<Invocation::Matcher *> &into) const = 0;


        virtual void getInvolvedMocks(std::vector<ActualInvocationsSource *> &into) const = 0;

        virtual unsigned int size() const = 0;

        friend class VerifyFunctor;
    };

    class ConcatenatedSequence : public virtual Sequence {
    private:
        const Sequence &s1;
        const Sequence &s2;

    protected:
        ConcatenatedSequence(const Sequence &seq1, const Sequence &seq2) :
                s1(seq1), s2(seq2) {
        }

    public:

        virtual ~ConcatenatedSequence() {
        }

        unsigned int size() const override {
            return s1.size() + s2.size();
        }

        const Sequence &getLeft() const {
            return s1;
        }

        const Sequence &getRight() const {
            return s2;
        }

        void getExpectedSequence(std::vector<Invocation::Matcher *> &into) const override {
            s1.getExpectedSequence(into);
            s2.getExpectedSequence(into);
        }

        virtual void getInvolvedMocks(std::vector<ActualInvocationsSource *> &into) const override {
            s1.getInvolvedMocks(into);
            s2.getInvolvedMocks(into);
        }

        friend inline ConcatenatedSequence operator+(const Sequence &s1, const Sequence &s2);
    };

    class RepeatedSequence : public virtual Sequence {
    private:
        const Sequence &_s;
        const int times;

    protected:
        RepeatedSequence(const Sequence &s, const int t) :
                _s(s), times(t) {
        }

    public:

        ~RepeatedSequence() {
        }

        unsigned int size() const override {
            return _s.size() * times;
        }

        friend inline RepeatedSequence operator*(const Sequence &s, int times);

        friend inline RepeatedSequence operator*(int times, const Sequence &s);

        void getInvolvedMocks(std::vector<ActualInvocationsSource *> &into) const override {
            _s.getInvolvedMocks(into);
        }

        void getExpectedSequence(std::vector<Invocation::Matcher *> &into) const override {
            for (int i = 0; i < times; i++)
                _s.getExpectedSequence(into);
        }

        int getTimes() const {
            return times;
        }

        const Sequence &getSequence() const {
            return _s;
        }
    };

    inline ConcatenatedSequence operator+(const Sequence &s1, const Sequence &s2) {
        return ConcatenatedSequence(s1, s2);
    }

    inline RepeatedSequence operator*(const Sequence &s, int times) {
        if (times <= 0)
            throw std::invalid_argument("times");
        return RepeatedSequence(s, times);
    }

    inline RepeatedSequence operator*(int times, const Sequence &s) {
        if (times <= 0)
            throw std::invalid_argument("times");
        return RepeatedSequence(s, times);
    }

}

namespace fakeit {

    enum class VerificationType {
        Exact, AtLeast, NoMoreInvocations
    };

    enum class UnexpectedType {
        Unmocked, Unmatched
    };

    struct VerificationEvent {

        VerificationEvent(VerificationType aVerificationType) :
                _verificationType(aVerificationType), _line(0) {
        }

        virtual ~VerificationEvent() = default;

        VerificationType verificationType() const {
            return _verificationType;
        }

        void setFileInfo(const char * aFile, int aLine, const char * aCallingMethod) {
            _file = aFile;
            _callingMethod = aCallingMethod;
            _line = aLine;
        }

        const char * file() const {
            return _file;
        }

        int line() const {
            return _line;
        }

        const char * callingMethod() const {
            return _callingMethod;
        }

    private:
        VerificationType _verificationType;
		const char * _file;
        int _line;
        const char * _callingMethod;
    };

    struct NoMoreInvocationsVerificationEvent : public VerificationEvent {

        ~NoMoreInvocationsVerificationEvent() = default;

        NoMoreInvocationsVerificationEvent(
                std::vector<Invocation *> &allTheIvocations,
                std::vector<Invocation *> &anUnverifedIvocations) :
                VerificationEvent(VerificationType::NoMoreInvocations),
                _allIvocations(allTheIvocations),
                _unverifedIvocations(anUnverifedIvocations) {
        }

        const std::vector<Invocation *> &allIvocations() const {
            return _allIvocations;
        }

        const std::vector<Invocation *> &unverifedIvocations() const {
            return _unverifedIvocations;
        }

    private:
        const std::vector<Invocation *> _allIvocations;
        const std::vector<Invocation *> _unverifedIvocations;
    };

    struct SequenceVerificationEvent : public VerificationEvent {

        ~SequenceVerificationEvent() = default;

        SequenceVerificationEvent(VerificationType aVerificationType,
                                  std::vector<Sequence *> &anExpectedPattern,
                                  std::vector<Invocation *> &anActualSequence,
                                  int anExpectedCount,
                                  int anActualCount) :
                VerificationEvent(aVerificationType),
                _expectedPattern(anExpectedPattern),
                _actualSequence(anActualSequence),
                _expectedCount(anExpectedCount),
                _actualCount(anActualCount)
        {
        }

        const std::vector<Sequence *> &expectedPattern() const {
            return _expectedPattern;
        }

        const std::vector<Invocation *> &actualSequence() const {
            return _actualSequence;
        }

        int expectedCount() const {
            return _expectedCount;
        }

        int actualCount() const {
            return _actualCount;
        }

    private:
        const std::vector<Sequence *> _expectedPattern;
        const std::vector<Invocation *> _actualSequence;
        const int _expectedCount;
        const int _actualCount;
    };

    struct UnexpectedMethodCallEvent {
        UnexpectedMethodCallEvent(UnexpectedType unexpectedType, const Invocation &invocation) :
                _unexpectedType(unexpectedType), _invocation(invocation) {
        }

        const Invocation &getInvocation() const {
            return _invocation;
        }

        UnexpectedType getUnexpectedType() const {
            return _unexpectedType;
        }

        const UnexpectedType _unexpectedType;
        const Invocation &_invocation;
    };

}

namespace fakeit {

    struct VerificationEventHandler {
        virtual void handle(const SequenceVerificationEvent &e) = 0;

        virtual void handle(const NoMoreInvocationsVerificationEvent &e) = 0;
    };

    struct EventHandler : public VerificationEventHandler {
        using VerificationEventHandler::handle;

        virtual void handle(const UnexpectedMethodCallEvent &e) = 0;
    };

}
#include <vector>
#include <string>

namespace fakeit {

    struct UnexpectedMethodCallEvent;
    struct SequenceVerificationEvent;
    struct NoMoreInvocationsVerificationEvent;

    struct EventFormatter {

        virtual std::string format(const fakeit::UnexpectedMethodCallEvent &e) = 0;

        virtual std::string format(const fakeit::SequenceVerificationEvent &e) = 0;

        virtual std::string format(const fakeit::NoMoreInvocationsVerificationEvent &e) = 0;

    };

}
#ifdef FAKEIT_ASSERT_ON_UNEXPECTED_METHOD_INVOCATION
#include <cassert>
#endif

namespace fakeit {

    struct FakeitContext : public EventHandler, protected EventFormatter {

        virtual ~FakeitContext() = default;

        void handle(const UnexpectedMethodCallEvent &e) override {
            fireEvent(e);
            auto &eh = getTestingFrameworkAdapter();
            #ifdef FAKEIT_ASSERT_ON_UNEXPECTED_METHOD_INVOCATION
            assert(!"Unexpected method invocation");
            #endif
            eh.handle(e);
        }

        void handle(const SequenceVerificationEvent &e) override {
            fireEvent(e);
            auto &eh = getTestingFrameworkAdapter();
            return eh.handle(e);
        }

        void handle(const NoMoreInvocationsVerificationEvent &e) override {
            fireEvent(e);
            auto &eh = getTestingFrameworkAdapter();
            return eh.handle(e);
        }

        std::string format(const UnexpectedMethodCallEvent &e) override {
            auto &eventFormatter = getEventFormatter();
            return eventFormatter.format(e);
        }

        std::string format(const SequenceVerificationEvent &e) override {
            auto &eventFormatter = getEventFormatter();
            return eventFormatter.format(e);
        }

        std::string format(const NoMoreInvocationsVerificationEvent &e) override {
            auto &eventFormatter = getEventFormatter();
            return eventFormatter.format(e);
        }

        void addEventHandler(EventHandler &eventListener) {
            _eventListeners.push_back(&eventListener);
        }

        void clearEventHandlers() {
            _eventListeners.clear();
        }

    protected:
        virtual EventHandler &getTestingFrameworkAdapter() = 0;

        virtual EventFormatter &getEventFormatter() = 0;

    private:
        std::vector<EventHandler *> _eventListeners;

        void fireEvent(const NoMoreInvocationsVerificationEvent &evt) {
            for (auto listener : _eventListeners)
                listener->handle(evt);
        }

        void fireEvent(const UnexpectedMethodCallEvent &evt) {
            for (auto listener : _eventListeners)
                listener->handle(evt);
        }

        void fireEvent(const SequenceVerificationEvent &evt) {
            for (auto listener : _eventListeners)
                listener->handle(evt);
        }

    };

}
#include <iostream>
#include <iosfwd>

namespace fakeit {

    struct DefaultEventFormatter : public EventFormatter {

        virtual std::string format(const UnexpectedMethodCallEvent &e) override {
            std::ostringstream out;
            out << "Unexpected method invocation: ";
            out << e.getInvocation().format() << std::endl;
            if (UnexpectedType::Unmatched == e.getUnexpectedType()) {
                out << "  Could not find any recorded behavior to support this method call.";
            } else {
                out << "  An unmocked method was invoked. All used virtual methods must be stubbed!";
            }
            return out.str();
        }


        virtual std::string format(const SequenceVerificationEvent &e) override {
            std::ostringstream out;
            out << "Verification error" << std::endl;

            out << "Expected pattern: ";
            const std::vector<fakeit::Sequence *> expectedPattern = e.expectedPattern();
            out << formatExpectedPattern(expectedPattern) << std::endl;

            out << "Expected matches: ";
            formatExpectedCount(out, e.verificationType(), e.expectedCount());
            out << std::endl;

            out << "Actual matches  : " << e.actualCount() << std::endl;

            auto actualSequence = e.actualSequence();
            out << "Actual sequence : total of " << actualSequence.size() << " actual invocations";
            if (actualSequence.size() == 0) {
                out << ".";
            } else {
                out << ":" << std::endl;
            }
            formatInvocationList(out, actualSequence);

            return out.str();
        }

        virtual std::string format(const NoMoreInvocationsVerificationEvent &e) override {
            std::ostringstream out;
            out << "Verification error" << std::endl;
            out << "Expected no more invocations!! but the following unverified invocations were found:" << std::endl;
            formatInvocationList(out, e.unverifedIvocations());
            return out.str();
        }

        static std::string formatExpectedPattern(const std::vector<fakeit::Sequence *> &expectedPattern) {
            std::string expectedPatternStr;
            for (unsigned int i = 0; i < expectedPattern.size(); i++) {
                Sequence *s = expectedPattern[i];
                expectedPatternStr += formatSequence(*s);
                if (i < expectedPattern.size() - 1)
                    expectedPatternStr += " ... ";
            }
            return expectedPatternStr;
        }

    private:

        static std::string formatSequence(const Sequence &val) {
            const ConcatenatedSequence *cs = dynamic_cast<const ConcatenatedSequence *>(&val);
            if (cs) {
                return format(*cs);
            }
            const RepeatedSequence *rs = dynamic_cast<const RepeatedSequence *>(&val);
            if (rs) {
                return format(*rs);
            }


            std::vector<Invocation::Matcher *> vec;
            val.getExpectedSequence(vec);
            return vec[0]->format();
        }

        static void formatExpectedCount(std::ostream &out, fakeit::VerificationType verificationType,
                                        int expectedCount) {
            if (verificationType == fakeit::VerificationType::Exact)
                out << "exactly ";

            if (verificationType == fakeit::VerificationType::AtLeast)
                out << "at least ";

            out << expectedCount;
        }

        static void formatInvocationList(std::ostream &out, const std::vector<fakeit::Invocation *> &actualSequence) {
            size_t max_size = actualSequence.size();
            if (max_size > 50)
                max_size = 50;

            for (unsigned int i = 0; i < max_size; i++) {
                out << "  ";
                auto invocation = actualSequence[i];
                out << invocation->format();
                if (i < max_size - 1)
                    out << std::endl;
            }

            if (actualSequence.size() > max_size)
                out << std::endl << "  ...";
        }

        static std::string format(const ConcatenatedSequence &val) {
            std::ostringstream out;
            out << formatSequence(val.getLeft()) << " + " << formatSequence(val.getRight());
            return out.str();
        }

        static std::string format(const RepeatedSequence &val) {
            std::ostringstream out;
            const ConcatenatedSequence *cs = dynamic_cast<const ConcatenatedSequence *>(&val.getSequence());
            const RepeatedSequence *rs = dynamic_cast<const RepeatedSequence *>(&val.getSequence());
            if (rs || cs)
                out << '(';
            out << formatSequence(val.getSequence());
            if (rs || cs)
                out << ')';

            out << " * " << val.getTimes();
            return out.str();
        }
    };
}
namespace fakeit {

    struct FakeitException {
        std::exception err;

        virtual ~FakeitException() = default;

        virtual std::string what() const = 0;

        friend std::ostream &operator<<(std::ostream &os, const FakeitException &val) {
            os << val.what();
            return os;
        }
    };




    struct UnexpectedMethodCallException : public FakeitException {

        UnexpectedMethodCallException(std::string format) :
                _format(format) {
        }

        virtual std::string what() const override {
            return _format;
        }

    private:
        std::string _format;
    };

}

namespace fakeit {

    struct DefaultEventLogger : public fakeit::EventHandler {

        DefaultEventLogger(EventFormatter &formatter) : _formatter(formatter), _out(std::cout) { }

        virtual void handle(const UnexpectedMethodCallEvent &e) override {
            _out << _formatter.format(e) << std::endl;
        }

        virtual void handle(const SequenceVerificationEvent &e) override {
            _out << _formatter.format(e) << std::endl;
        }

        virtual void handle(const NoMoreInvocationsVerificationEvent &e) override {
            _out << _formatter.format(e) << std::endl;
        }

    private:
        EventFormatter &_formatter;
        std::ostream &_out;
    };

}

namespace fakeit {

    class AbstractFakeit : public FakeitContext {
    public:
        virtual ~AbstractFakeit() = default;

    protected:

        virtual fakeit::EventHandler &accessTestingFrameworkAdapter() = 0;

        virtual EventFormatter &accessEventFormatter() = 0;
    };

    class DefaultFakeit : public AbstractFakeit {
        DefaultEventFormatter _formatter;
        fakeit::EventFormatter *_customFormatter;
        fakeit::EventHandler *_testingFrameworkAdapter;

    public:

        DefaultFakeit() : _formatter(),
                          _customFormatter(nullptr),
                          _testingFrameworkAdapter(nullptr) {
        }

        virtual ~DefaultFakeit() = default;

        void setCustomEventFormatter(fakeit::EventFormatter &customEventFormatter) {
            _customFormatter = &customEventFormatter;
        }

        void resetCustomEventFormatter() {
            _customFormatter = nullptr;
        }

        void setTestingFrameworkAdapter(fakeit::EventHandler &testingFrameforkAdapter) {
            _testingFrameworkAdapter = &testingFrameforkAdapter;
        }

        void resetTestingFrameworkAdapter() {
            _testingFrameworkAdapter = nullptr;
        }

    protected:

        fakeit::EventHandler &getTestingFrameworkAdapter() override {
            if (_testingFrameworkAdapter)
                return *_testingFrameworkAdapter;
            return accessTestingFrameworkAdapter();
        }

        EventFormatter &getEventFormatter() override {
            if (_customFormatter)
                return *_customFormatter;
            return accessEventFormatter();
        }

        EventFormatter &accessEventFormatter() override {
            return _formatter;
        }

    };
}
#include <string>
#include <sstream>
#include <iomanip>

namespace fakeit {

    template<typename T>
    static std::string to_string(const T &n) {
        std::ostringstream stm;
        stm << n;
        return stm.str();
    }

}

namespace fakeit {

    struct VerificationException : public FakeitException {
        virtual ~VerificationException() = default;

        void setFileInfo(const char *file, int line, const char *callingMethod) {
            _file = file;
            _callingMethod = callingMethod;
            _line = line;
        }

        const char *file() const {
            return _file;
        }

        int line() const {
            return _line;
        }

        const char *callingMethod() const {
            return _callingMethod;
        }

    private:
        const char *_file;
        int _line;
        const char *_callingMethod;
    };

    struct NoMoreInvocationsVerificationException : public VerificationException {

        NoMoreInvocationsVerificationException(std::string format) :
                _format(format) {
        }

        virtual std::string what() const override {
            return _format;
        }

    private:
        std::string _format;
    };

    struct SequenceVerificationException : public VerificationException {
        SequenceVerificationException(const std::string &format) :
                _format(format)
        {
        }

        virtual std::string what() const override {
            return _format;
        }

    private:
        std::string _format;
    };

    class CatchAdapter : public EventHandler {
        EventFormatter &_formatter;

        std::string formatLineNumber(std::string file, int num) {
#ifndef __GNUG__
            return file + std::string("(") + fakeit::to_string(num) + std::string(")");
#else
            return file + std::string(":") + fakeit::to_string(num);
#endif
        }

    public:

        virtual ~CatchAdapter() = default;

        CatchAdapter(EventFormatter &formatter)
                : _formatter(formatter) {}

        void fail(
                std::string vetificationType,
                Catch::SourceLineInfo sourceLineInfo,
                std::string failingExpression,
                std::string fomattedMessage,
                Catch::ResultWas::OfType resultWas = Catch::ResultWas::OfType::ExpressionFailed ){
            Catch::AssertionHandler catchAssertionHandler( vetificationType, sourceLineInfo, failingExpression, Catch::ResultDisposition::Normal );
            INTERNAL_CATCH_TRY { \
                CATCH_INTERNAL_SUPPRESS_PARENTHESES_WARNINGS \
                catchAssertionHandler.handleMessage(resultWas, fomattedMessage); \
                CATCH_INTERNAL_UNSUPPRESS_PARENTHESES_WARNINGS \
            } INTERNAL_CATCH_CATCH(catchAssertionHandler) { \
                INTERNAL_CATCH_REACT(catchAssertionHandler) \
            }
        }

        virtual void handle(const UnexpectedMethodCallEvent &evt) override {
            std::string format = _formatter.format(evt);
            fail("UnexpectedMethodCall",::Catch::SourceLineInfo("Unknown file",0),"",format, Catch::ResultWas::OfType::ExplicitFailure);
        }

        virtual void handle(const SequenceVerificationEvent &evt) override {
            std::string format(formatLineNumber(evt.file(), evt.line()) + ": " + _formatter.format(evt));
            std::string expectedPattern {DefaultEventFormatter::formatExpectedPattern(evt.expectedPattern())};
            fail("Verify",::Catch::SourceLineInfo(evt.file(),evt.line()),expectedPattern,format);
        }


        virtual void handle(const NoMoreInvocationsVerificationEvent &evt) override {
            std::string format(formatLineNumber(evt.file(), evt.line()) + ": " + _formatter.format(evt));
            fail("VerifyNoMoreInvocations",::Catch::SourceLineInfo(evt.file(),evt.line()),"",format);
        }

    };


    class CatchFakeit : public DefaultFakeit {


    public:

        virtual ~CatchFakeit() = default;

        CatchFakeit() : _formatter(), _catchAdapter(_formatter) {}

        static CatchFakeit &getInstance() {
            static CatchFakeit instance;
            return instance;
        }

    protected:

        fakeit::EventHandler &accessTestingFrameworkAdapter() override {
            return _catchAdapter;
        }

        EventFormatter &accessEventFormatter() override {
            return _formatter;
        }

    private:

        DefaultEventFormatter _formatter;
        CatchAdapter _catchAdapter;
    };

}

static fakeit::DefaultFakeit& Fakeit = fakeit::CatchFakeit::getInstance();


#include <type_traits>
#include <unordered_set>

#include <memory>
#undef max
#include <functional>
#include <type_traits>
#include <vector>
#include <array>
#include <new>
#include <limits>

#include <functional>
#include <type_traits>
namespace fakeit {

    struct VirtualOffsetSelector {

        unsigned int offset;

        virtual unsigned int offset0(int) {
            return offset = 0;
        }

        virtual unsigned int offset1(int) {
            return offset = 1;
        }

        virtual unsigned int offset2(int) {
            return offset = 2;
        }

        virtual unsigned int offset3(int) {
            return offset = 3;
        }

        virtual unsigned int offset4(int) {
            return offset = 4;
        }

        virtual unsigned int offset5(int) {
            return offset = 5;
        }

        virtual unsigned int offset6(int) {
            return offset = 6;
        }

        virtual unsigned int offset7(int) {
            return offset = 7;
        }

        virtual unsigned int offset8(int) {
            return offset = 8;
        }

        virtual unsigned int offset9(int) {
            return offset = 9;
        }

        virtual unsigned int offset10(int) {
            return offset = 10;
        }

        virtual unsigned int offset11(int) {
            return offset = 11;
        }

        virtual unsigned int offset12(int) {
            return offset = 12;
        }

        virtual unsigned int offset13(int) {
            return offset = 13;
        }

        virtual unsigned int offset14(int) {
            return offset = 14;
        }

        virtual unsigned int offset15(int) {
            return offset = 15;
        }

        virtual unsigned int offset16(int) {
            return offset = 16;
        }

        virtual unsigned int offset17(int) {
            return offset = 17;
        }

        virtual unsigned int offset18(int) {
            return offset = 18;
        }

        virtual unsigned int offset19(int) {
            return offset = 19;
        }

        virtual unsigned int offset20(int) {
            return offset = 20;
        }

        virtual unsigned int offset21(int) {
            return offset = 21;
        }

        virtual unsigned int offset22(int) {
            return offset = 22;
        }

        virtual unsigned int offset23(int) {
            return offset = 23;
        }

        virtual unsigned int offset24(int) {
            return offset = 24;
        }

        virtual unsigned int offset25(int) {
            return offset = 25;
        }

        virtual unsigned int offset26(int) {
            return offset = 26;
        }

        virtual unsigned int offset27(int) {
            return offset = 27;
        }

        virtual unsigned int offset28(int) {
            return offset = 28;
        }

        virtual unsigned int offset29(int) {
            return offset = 29;
        }

        virtual unsigned int offset30(int) {
            return offset = 30;
        }

        virtual unsigned int offset31(int) {
            return offset = 31;
        }

        virtual unsigned int offset32(int) {
            return offset = 32;
        }

        virtual unsigned int offset33(int) {
            return offset = 33;
        }

        virtual unsigned int offset34(int) {
            return offset = 34;
        }

        virtual unsigned int offset35(int) {
            return offset = 35;
        }

        virtual unsigned int offset36(int) {
            return offset = 36;
        }

        virtual unsigned int offset37(int) {
            return offset = 37;
        }

        virtual unsigned int offset38(int) {
            return offset = 38;
        }

        virtual unsigned int offset39(int) {
            return offset = 39;
        }

        virtual unsigned int offset40(int) {
            return offset = 40;
        }

        virtual unsigned int offset41(int) {
            return offset = 41;
        }

        virtual unsigned int offset42(int) {
            return offset = 42;
        }

        virtual unsigned int offset43(int) {
            return offset = 43;
        }

        virtual unsigned int offset44(int) {
            return offset = 44;
        }

        virtual unsigned int offset45(int) {
            return offset = 45;
        }

        virtual unsigned int offset46(int) {
            return offset = 46;
        }

        virtual unsigned int offset47(int) {
            return offset = 47;
        }

        virtual unsigned int offset48(int) {
            return offset = 48;
        }

        virtual unsigned int offset49(int) {
            return offset = 49;
        }

        virtual unsigned int offset50(int) {
            return offset = 50;
        }

        virtual unsigned int offset51(int) {
            return offset = 51;
        }

        virtual unsigned int offset52(int) {
            return offset = 52;
        }

        virtual unsigned int offset53(int) {
            return offset = 53;
        }

        virtual unsigned int offset54(int) {
            return offset = 54;
        }

        virtual unsigned int offset55(int) {
            return offset = 55;
        }

        virtual unsigned int offset56(int) {
            return offset = 56;
        }

        virtual unsigned int offset57(int) {
            return offset = 57;
        }

        virtual unsigned int offset58(int) {
            return offset = 58;
        }

        virtual unsigned int offset59(int) {
            return offset = 59;
        }

        virtual unsigned int offset60(int) {
            return offset = 60;
        }

        virtual unsigned int offset61(int) {
            return offset = 61;
        }

        virtual unsigned int offset62(int) {
            return offset = 62;
        }

        virtual unsigned int offset63(int) {
            return offset = 63;
        }

        virtual unsigned int offset64(int) {
            return offset = 64;
        }

        virtual unsigned int offset65(int) {
            return offset = 65;
        }

        virtual unsigned int offset66(int) {
            return offset = 66;
        }

        virtual unsigned int offset67(int) {
            return offset = 67;
        }

        virtual unsigned int offset68(int) {
            return offset = 68;
        }

        virtual unsigned int offset69(int) {
            return offset = 69;
        }

        virtual unsigned int offset70(int) {
            return offset = 70;
        }

        virtual unsigned int offset71(int) {
            return offset = 71;
        }

        virtual unsigned int offset72(int) {
            return offset = 72;
        }

        virtual unsigned int offset73(int) {
            return offset = 73;
        }

        virtual unsigned int offset74(int) {
            return offset = 74;
        }

        virtual unsigned int offset75(int) {
            return offset = 75;
        }

        virtual unsigned int offset76(int) {
            return offset = 76;
        }

        virtual unsigned int offset77(int) {
            return offset = 77;
        }

        virtual unsigned int offset78(int) {
            return offset = 78;
        }

        virtual unsigned int offset79(int) {
            return offset = 79;
        }

        virtual unsigned int offset80(int) {
            return offset = 80;
        }

        virtual unsigned int offset81(int) {
            return offset = 81;
        }

        virtual unsigned int offset82(int) {
            return offset = 82;
        }

        virtual unsigned int offset83(int) {
            return offset = 83;
        }

        virtual unsigned int offset84(int) {
            return offset = 84;
        }

        virtual unsigned int offset85(int) {
            return offset = 85;
        }

        virtual unsigned int offset86(int) {
            return offset = 86;
        }

        virtual unsigned int offset87(int) {
            return offset = 87;
        }

        virtual unsigned int offset88(int) {
            return offset = 88;
        }

        virtual unsigned int offset89(int) {
            return offset = 89;
        }

        virtual unsigned int offset90(int) {
            return offset = 90;
        }

        virtual unsigned int offset91(int) {
            return offset = 91;
        }

        virtual unsigned int offset92(int) {
            return offset = 92;
        }

        virtual unsigned int offset93(int) {
            return offset = 93;
        }

        virtual unsigned int offset94(int) {
            return offset = 94;
        }

        virtual unsigned int offset95(int) {
            return offset = 95;
        }

        virtual unsigned int offset96(int) {
            return offset = 96;
        }

        virtual unsigned int offset97(int) {
            return offset = 97;
        }

        virtual unsigned int offset98(int) {
            return offset = 98;
        }

        virtual unsigned int offset99(int) {
            return offset = 99;
        }

        virtual unsigned int offset100(int) {
            return offset = 100;
        }

        virtual unsigned int offset101(int) {
            return offset = 101;
        }

        virtual unsigned int offset102(int) {
            return offset = 102;
        }

        virtual unsigned int offset103(int) {
            return offset = 103;
        }

        virtual unsigned int offset104(int) {
            return offset = 104;
        }

        virtual unsigned int offset105(int) {
            return offset = 105;
        }

        virtual unsigned int offset106(int) {
            return offset = 106;
        }

        virtual unsigned int offset107(int) {
            return offset = 107;
        }

        virtual unsigned int offset108(int) {
            return offset = 108;
        }

        virtual unsigned int offset109(int) {
            return offset = 109;
        }

        virtual unsigned int offset110(int) {
            return offset = 110;
        }

        virtual unsigned int offset111(int) {
            return offset = 111;
        }

        virtual unsigned int offset112(int) {
            return offset = 112;
        }

        virtual unsigned int offset113(int) {
            return offset = 113;
        }

        virtual unsigned int offset114(int) {
            return offset = 114;
        }

        virtual unsigned int offset115(int) {
            return offset = 115;
        }

        virtual unsigned int offset116(int) {
            return offset = 116;
        }

        virtual unsigned int offset117(int) {
            return offset = 117;
        }

        virtual unsigned int offset118(int) {
            return offset = 118;
        }

        virtual unsigned int offset119(int) {
            return offset = 119;
        }

        virtual unsigned int offset120(int) {
            return offset = 120;
        }

        virtual unsigned int offset121(int) {
            return offset = 121;
        }

        virtual unsigned int offset122(int) {
            return offset = 122;
        }

        virtual unsigned int offset123(int) {
            return offset = 123;
        }

        virtual unsigned int offset124(int) {
            return offset = 124;
        }

        virtual unsigned int offset125(int) {
            return offset = 125;
        }

        virtual unsigned int offset126(int) {
            return offset = 126;
        }

        virtual unsigned int offset127(int) {
            return offset = 127;
        }

        virtual unsigned int offset128(int) {
            return offset = 128;
        }

        virtual unsigned int offset129(int) {
            return offset = 129;
        }

        virtual unsigned int offset130(int) {
            return offset = 130;
        }

        virtual unsigned int offset131(int) {
            return offset = 131;
        }

        virtual unsigned int offset132(int) {
            return offset = 132;
        }

        virtual unsigned int offset133(int) {
            return offset = 133;
        }

        virtual unsigned int offset134(int) {
            return offset = 134;
        }

        virtual unsigned int offset135(int) {
            return offset = 135;
        }

        virtual unsigned int offset136(int) {
            return offset = 136;
        }

        virtual unsigned int offset137(int) {
            return offset = 137;
        }

        virtual unsigned int offset138(int) {
            return offset = 138;
        }

        virtual unsigned int offset139(int) {
            return offset = 139;
        }

        virtual unsigned int offset140(int) {
            return offset = 140;
        }

        virtual unsigned int offset141(int) {
            return offset = 141;
        }

        virtual unsigned int offset142(int) {
            return offset = 142;
        }

        virtual unsigned int offset143(int) {
            return offset = 143;
        }

        virtual unsigned int offset144(int) {
            return offset = 144;
        }

        virtual unsigned int offset145(int) {
            return offset = 145;
        }

        virtual unsigned int offset146(int) {
            return offset = 146;
        }

        virtual unsigned int offset147(int) {
            return offset = 147;
        }

        virtual unsigned int offset148(int) {
            return offset = 148;
        }

        virtual unsigned int offset149(int) {
            return offset = 149;
        }

        virtual unsigned int offset150(int) {
            return offset = 150;
        }

        virtual unsigned int offset151(int) {
            return offset = 151;
        }

        virtual unsigned int offset152(int) {
            return offset = 152;
        }

        virtual unsigned int offset153(int) {
            return offset = 153;
        }

        virtual unsigned int offset154(int) {
            return offset = 154;
        }

        virtual unsigned int offset155(int) {
            return offset = 155;
        }

        virtual unsigned int offset156(int) {
            return offset = 156;
        }

        virtual unsigned int offset157(int) {
            return offset = 157;
        }

        virtual unsigned int offset158(int) {
            return offset = 158;
        }

        virtual unsigned int offset159(int) {
            return offset = 159;
        }

        virtual unsigned int offset160(int) {
            return offset = 160;
        }

        virtual unsigned int offset161(int) {
            return offset = 161;
        }

        virtual unsigned int offset162(int) {
            return offset = 162;
        }

        virtual unsigned int offset163(int) {
            return offset = 163;
        }

        virtual unsigned int offset164(int) {
            return offset = 164;
        }

        virtual unsigned int offset165(int) {
            return offset = 165;
        }

        virtual unsigned int offset166(int) {
            return offset = 166;
        }

        virtual unsigned int offset167(int) {
            return offset = 167;
        }

        virtual unsigned int offset168(int) {
            return offset = 168;
        }

        virtual unsigned int offset169(int) {
            return offset = 169;
        }

        virtual unsigned int offset170(int) {
            return offset = 170;
        }

        virtual unsigned int offset171(int) {
            return offset = 171;
        }

        virtual unsigned int offset172(int) {
            return offset = 172;
        }

        virtual unsigned int offset173(int) {
            return offset = 173;
        }

        virtual unsigned int offset174(int) {
            return offset = 174;
        }

        virtual unsigned int offset175(int) {
            return offset = 175;
        }

        virtual unsigned int offset176(int) {
            return offset = 176;
        }

        virtual unsigned int offset177(int) {
            return offset = 177;
        }

        virtual unsigned int offset178(int) {
            return offset = 178;
        }

        virtual unsigned int offset179(int) {
            return offset = 179;
        }

        virtual unsigned int offset180(int) {
            return offset = 180;
        }

        virtual unsigned int offset181(int) {
            return offset = 181;
        }

        virtual unsigned int offset182(int) {
            return offset = 182;
        }

        virtual unsigned int offset183(int) {
            return offset = 183;
        }

        virtual unsigned int offset184(int) {
            return offset = 184;
        }

        virtual unsigned int offset185(int) {
            return offset = 185;
        }

        virtual unsigned int offset186(int) {
            return offset = 186;
        }

        virtual unsigned int offset187(int) {
            return offset = 187;
        }

        virtual unsigned int offset188(int) {
            return offset = 188;
        }

        virtual unsigned int offset189(int) {
            return offset = 189;
        }

        virtual unsigned int offset190(int) {
            return offset = 190;
        }

        virtual unsigned int offset191(int) {
            return offset = 191;
        }

        virtual unsigned int offset192(int) {
            return offset = 192;
        }

        virtual unsigned int offset193(int) {
            return offset = 193;
        }

        virtual unsigned int offset194(int) {
            return offset = 194;
        }

        virtual unsigned int offset195(int) {
            return offset = 195;
        }

        virtual unsigned int offset196(int) {
            return offset = 196;
        }

        virtual unsigned int offset197(int) {
            return offset = 197;
        }

        virtual unsigned int offset198(int) {
            return offset = 198;
        }

        virtual unsigned int offset199(int) {
            return offset = 199;
        }


        virtual unsigned int offset200(int) {
            return offset = 200;
        }

        virtual unsigned int offset201(int) {
            return offset = 201;
        }

        virtual unsigned int offset202(int) {
            return offset = 202;
        }

        virtual unsigned int offset203(int) {
            return offset = 203;
        }

        virtual unsigned int offset204(int) {
            return offset = 204;
        }

        virtual unsigned int offset205(int) {
            return offset = 205;
        }

        virtual unsigned int offset206(int) {
            return offset = 206;
        }

        virtual unsigned int offset207(int) {
            return offset = 207;
        }

        virtual unsigned int offset208(int) {
            return offset = 208;
        }

        virtual unsigned int offset209(int) {
            return offset = 209;
        }

        virtual unsigned int offset210(int) {
            return offset = 210;
        }

        virtual unsigned int offset211(int) {
            return offset = 211;
        }

        virtual unsigned int offset212(int) {
            return offset = 212;
        }

        virtual unsigned int offset213(int) {
            return offset = 213;
        }

        virtual unsigned int offset214(int) {
            return offset = 214;
        }

        virtual unsigned int offset215(int) {
            return offset = 215;
        }

        virtual unsigned int offset216(int) {
            return offset = 216;
        }

        virtual unsigned int offset217(int) {
            return offset = 217;
        }

        virtual unsigned int offset218(int) {
            return offset = 218;
        }

        virtual unsigned int offset219(int) {
            return offset = 219;
        }

        virtual unsigned int offset220(int) {
            return offset = 220;
        }

        virtual unsigned int offset221(int) {
            return offset = 221;
        }

        virtual unsigned int offset222(int) {
            return offset = 222;
        }

        virtual unsigned int offset223(int) {
            return offset = 223;
        }

        virtual unsigned int offset224(int) {
            return offset = 224;
        }

        virtual unsigned int offset225(int) {
            return offset = 225;
        }

        virtual unsigned int offset226(int) {
            return offset = 226;
        }

        virtual unsigned int offset227(int) {
            return offset = 227;
        }

        virtual unsigned int offset228(int) {
            return offset = 228;
        }

        virtual unsigned int offset229(int) {
            return offset = 229;
        }

        virtual unsigned int offset230(int) {
            return offset = 230;
        }

        virtual unsigned int offset231(int) {
            return offset = 231;
        }

        virtual unsigned int offset232(int) {
            return offset = 232;
        }

        virtual unsigned int offset233(int) {
            return offset = 233;
        }

        virtual unsigned int offset234(int) {
            return offset = 234;
        }

        virtual unsigned int offset235(int) {
            return offset = 235;
        }

        virtual unsigned int offset236(int) {
            return offset = 236;
        }

        virtual unsigned int offset237(int) {
            return offset = 237;
        }

        virtual unsigned int offset238(int) {
            return offset = 238;
        }

        virtual unsigned int offset239(int) {
            return offset = 239;
        }

        virtual unsigned int offset240(int) {
            return offset = 240;
        }

        virtual unsigned int offset241(int) {
            return offset = 241;
        }

        virtual unsigned int offset242(int) {
            return offset = 242;
        }

        virtual unsigned int offset243(int) {
            return offset = 243;
        }

        virtual unsigned int offset244(int) {
            return offset = 244;
        }

        virtual unsigned int offset245(int) {
            return offset = 245;
        }

        virtual unsigned int offset246(int) {
            return offset = 246;
        }

        virtual unsigned int offset247(int) {
            return offset = 247;
        }

        virtual unsigned int offset248(int) {
            return offset = 248;
        }

        virtual unsigned int offset249(int) {
            return offset = 249;
        }

        virtual unsigned int offset250(int) {
            return offset = 250;
        }

        virtual unsigned int offset251(int) {
            return offset = 251;
        }

        virtual unsigned int offset252(int) {
            return offset = 252;
        }

        virtual unsigned int offset253(int) {
            return offset = 253;
        }

        virtual unsigned int offset254(int) {
            return offset = 254;
        }

        virtual unsigned int offset255(int) {
            return offset = 255;
        }

        virtual unsigned int offset256(int) {
            return offset = 256;
        }

        virtual unsigned int offset257(int) {
            return offset = 257;
        }

        virtual unsigned int offset258(int) {
            return offset = 258;
        }

        virtual unsigned int offset259(int) {
            return offset = 259;
        }

        virtual unsigned int offset260(int) {
            return offset = 260;
        }

        virtual unsigned int offset261(int) {
            return offset = 261;
        }

        virtual unsigned int offset262(int) {
            return offset = 262;
        }

        virtual unsigned int offset263(int) {
            return offset = 263;
        }

        virtual unsigned int offset264(int) {
            return offset = 264;
        }

        virtual unsigned int offset265(int) {
            return offset = 265;
        }

        virtual unsigned int offset266(int) {
            return offset = 266;
        }

        virtual unsigned int offset267(int) {
            return offset = 267;
        }

        virtual unsigned int offset268(int) {
            return offset = 268;
        }

        virtual unsigned int offset269(int) {
            return offset = 269;
        }

        virtual unsigned int offset270(int) {
            return offset = 270;
        }

        virtual unsigned int offset271(int) {
            return offset = 271;
        }

        virtual unsigned int offset272(int) {
            return offset = 272;
        }

        virtual unsigned int offset273(int) {
            return offset = 273;
        }

        virtual unsigned int offset274(int) {
            return offset = 274;
        }

        virtual unsigned int offset275(int) {
            return offset = 275;
        }

        virtual unsigned int offset276(int) {
            return offset = 276;
        }

        virtual unsigned int offset277(int) {
            return offset = 277;
        }

        virtual unsigned int offset278(int) {
            return offset = 278;
        }

        virtual unsigned int offset279(int) {
            return offset = 279;
        }

        virtual unsigned int offset280(int) {
            return offset = 280;
        }

        virtual unsigned int offset281(int) {
            return offset = 281;
        }

        virtual unsigned int offset282(int) {
            return offset = 282;
        }

        virtual unsigned int offset283(int) {
            return offset = 283;
        }

        virtual unsigned int offset284(int) {
            return offset = 284;
        }

        virtual unsigned int offset285(int) {
            return offset = 285;
        }

        virtual unsigned int offset286(int) {
            return offset = 286;
        }

        virtual unsigned int offset287(int) {
            return offset = 287;
        }

        virtual unsigned int offset288(int) {
            return offset = 288;
        }

        virtual unsigned int offset289(int) {
            return offset = 289;
        }

        virtual unsigned int offset290(int) {
            return offset = 290;
        }

        virtual unsigned int offset291(int) {
            return offset = 291;
        }

        virtual unsigned int offset292(int) {
            return offset = 292;
        }

        virtual unsigned int offset293(int) {
            return offset = 293;
        }

        virtual unsigned int offset294(int) {
            return offset = 294;
        }

        virtual unsigned int offset295(int) {
            return offset = 295;
        }

        virtual unsigned int offset296(int) {
            return offset = 296;
        }

        virtual unsigned int offset297(int) {
            return offset = 297;
        }

        virtual unsigned int offset298(int) {
            return offset = 298;
        }

        virtual unsigned int offset299(int) {
            return offset = 299;
        }


        virtual unsigned int offset300(int) {
            return offset = 300;
        }

        virtual unsigned int offset301(int) {
            return offset = 301;
        }

        virtual unsigned int offset302(int) {
            return offset = 302;
        }

        virtual unsigned int offset303(int) {
            return offset = 303;
        }

        virtual unsigned int offset304(int) {
            return offset = 304;
        }

        virtual unsigned int offset305(int) {
            return offset = 305;
        }

        virtual unsigned int offset306(int) {
            return offset = 306;
        }

        virtual unsigned int offset307(int) {
            return offset = 307;
        }

        virtual unsigned int offset308(int) {
            return offset = 308;
        }

        virtual unsigned int offset309(int) {
            return offset = 309;
        }

        virtual unsigned int offset310(int) {
            return offset = 310;
        }

        virtual unsigned int offset311(int) {
            return offset = 311;
        }

        virtual unsigned int offset312(int) {
            return offset = 312;
        }

        virtual unsigned int offset313(int) {
            return offset = 313;
        }

        virtual unsigned int offset314(int) {
            return offset = 314;
        }

        virtual unsigned int offset315(int) {
            return offset = 315;
        }

        virtual unsigned int offset316(int) {
            return offset = 316;
        }

        virtual unsigned int offset317(int) {
            return offset = 317;
        }

        virtual unsigned int offset318(int) {
            return offset = 318;
        }

        virtual unsigned int offset319(int) {
            return offset = 319;
        }

        virtual unsigned int offset320(int) {
            return offset = 320;
        }

        virtual unsigned int offset321(int) {
            return offset = 321;
        }

        virtual unsigned int offset322(int) {
            return offset = 322;
        }

        virtual unsigned int offset323(int) {
            return offset = 323;
        }

        virtual unsigned int offset324(int) {
            return offset = 324;
        }

        virtual unsigned int offset325(int) {
            return offset = 325;
        }

        virtual unsigned int offset326(int) {
            return offset = 326;
        }

        virtual unsigned int offset327(int) {
            return offset = 327;
        }

        virtual unsigned int offset328(int) {
            return offset = 328;
        }

        virtual unsigned int offset329(int) {
            return offset = 329;
        }

        virtual unsigned int offset330(int) {
            return offset = 330;
        }

        virtual unsigned int offset331(int) {
            return offset = 331;
        }

        virtual unsigned int offset332(int) {
            return offset = 332;
        }

        virtual unsigned int offset333(int) {
            return offset = 333;
        }

        virtual unsigned int offset334(int) {
            return offset = 334;
        }

        virtual unsigned int offset335(int) {
            return offset = 335;
        }

        virtual unsigned int offset336(int) {
            return offset = 336;
        }

        virtual unsigned int offset337(int) {
            return offset = 337;
        }

        virtual unsigned int offset338(int) {
            return offset = 338;
        }

        virtual unsigned int offset339(int) {
            return offset = 339;
        }

        virtual unsigned int offset340(int) {
            return offset = 340;
        }

        virtual unsigned int offset341(int) {
            return offset = 341;
        }

        virtual unsigned int offset342(int) {
            return offset = 342;
        }

        virtual unsigned int offset343(int) {
            return offset = 343;
        }

        virtual unsigned int offset344(int) {
            return offset = 344;
        }

        virtual unsigned int offset345(int) {
            return offset = 345;
        }

        virtual unsigned int offset346(int) {
            return offset = 346;
        }

        virtual unsigned int offset347(int) {
            return offset = 347;
        }

        virtual unsigned int offset348(int) {
            return offset = 348;
        }

        virtual unsigned int offset349(int) {
            return offset = 349;
        }

        virtual unsigned int offset350(int) {
            return offset = 350;
        }

        virtual unsigned int offset351(int) {
            return offset = 351;
        }

        virtual unsigned int offset352(int) {
            return offset = 352;
        }

        virtual unsigned int offset353(int) {
            return offset = 353;
        }

        virtual unsigned int offset354(int) {
            return offset = 354;
        }

        virtual unsigned int offset355(int) {
            return offset = 355;
        }

        virtual unsigned int offset356(int) {
            return offset = 356;
        }

        virtual unsigned int offset357(int) {
            return offset = 357;
        }

        virtual unsigned int offset358(int) {
            return offset = 358;
        }

        virtual unsigned int offset359(int) {
            return offset = 359;
        }

        virtual unsigned int offset360(int) {
            return offset = 360;
        }

        virtual unsigned int offset361(int) {
            return offset = 361;
        }

        virtual unsigned int offset362(int) {
            return offset = 362;
        }

        virtual unsigned int offset363(int) {
            return offset = 363;
        }

        virtual unsigned int offset364(int) {
            return offset = 364;
        }

        virtual unsigned int offset365(int) {
            return offset = 365;
        }

        virtual unsigned int offset366(int) {
            return offset = 366;
        }

        virtual unsigned int offset367(int) {
            return offset = 367;
        }

        virtual unsigned int offset368(int) {
            return offset = 368;
        }

        virtual unsigned int offset369(int) {
            return offset = 369;
        }

        virtual unsigned int offset370(int) {
            return offset = 370;
        }

        virtual unsigned int offset371(int) {
            return offset = 371;
        }

        virtual unsigned int offset372(int) {
            return offset = 372;
        }

        virtual unsigned int offset373(int) {
            return offset = 373;
        }

        virtual unsigned int offset374(int) {
            return offset = 374;
        }

        virtual unsigned int offset375(int) {
            return offset = 375;
        }

        virtual unsigned int offset376(int) {
            return offset = 376;
        }

        virtual unsigned int offset377(int) {
            return offset = 377;
        }

        virtual unsigned int offset378(int) {
            return offset = 378;
        }

        virtual unsigned int offset379(int) {
            return offset = 379;
        }

        virtual unsigned int offset380(int) {
            return offset = 380;
        }

        virtual unsigned int offset381(int) {
            return offset = 381;
        }

        virtual unsigned int offset382(int) {
            return offset = 382;
        }

        virtual unsigned int offset383(int) {
            return offset = 383;
        }

        virtual unsigned int offset384(int) {
            return offset = 384;
        }

        virtual unsigned int offset385(int) {
            return offset = 385;
        }

        virtual unsigned int offset386(int) {
            return offset = 386;
        }

        virtual unsigned int offset387(int) {
            return offset = 387;
        }

        virtual unsigned int offset388(int) {
            return offset = 388;
        }

        virtual unsigned int offset389(int) {
            return offset = 389;
        }

        virtual unsigned int offset390(int) {
            return offset = 390;
        }

        virtual unsigned int offset391(int) {
            return offset = 391;
        }

        virtual unsigned int offset392(int) {
            return offset = 392;
        }

        virtual unsigned int offset393(int) {
            return offset = 393;
        }

        virtual unsigned int offset394(int) {
            return offset = 394;
        }

        virtual unsigned int offset395(int) {
            return offset = 395;
        }

        virtual unsigned int offset396(int) {
            return offset = 396;
        }

        virtual unsigned int offset397(int) {
            return offset = 397;
        }

        virtual unsigned int offset398(int) {
            return offset = 398;
        }

        virtual unsigned int offset399(int) {
            return offset = 399;
        }


        virtual unsigned int offset400(int) {
            return offset = 400;
        }

        virtual unsigned int offset401(int) {
            return offset = 401;
        }

        virtual unsigned int offset402(int) {
            return offset = 402;
        }

        virtual unsigned int offset403(int) {
            return offset = 403;
        }

        virtual unsigned int offset404(int) {
            return offset = 404;
        }

        virtual unsigned int offset405(int) {
            return offset = 405;
        }

        virtual unsigned int offset406(int) {
            return offset = 406;
        }

        virtual unsigned int offset407(int) {
            return offset = 407;
        }

        virtual unsigned int offset408(int) {
            return offset = 408;
        }

        virtual unsigned int offset409(int) {
            return offset = 409;
        }

        virtual unsigned int offset410(int) {
            return offset = 410;
        }

        virtual unsigned int offset411(int) {
            return offset = 411;
        }

        virtual unsigned int offset412(int) {
            return offset = 412;
        }

        virtual unsigned int offset413(int) {
            return offset = 413;
        }

        virtual unsigned int offset414(int) {
            return offset = 414;
        }

        virtual unsigned int offset415(int) {
            return offset = 415;
        }

        virtual unsigned int offset416(int) {
            return offset = 416;
        }

        virtual unsigned int offset417(int) {
            return offset = 417;
        }

        virtual unsigned int offset418(int) {
            return offset = 418;
        }

        virtual unsigned int offset419(int) {
            return offset = 419;
        }

        virtual unsigned int offset420(int) {
            return offset = 420;
        }

        virtual unsigned int offset421(int) {
            return offset = 421;
        }

        virtual unsigned int offset422(int) {
            return offset = 422;
        }

        virtual unsigned int offset423(int) {
            return offset = 423;
        }

        virtual unsigned int offset424(int) {
            return offset = 424;
        }

        virtual unsigned int offset425(int) {
            return offset = 425;
        }

        virtual unsigned int offset426(int) {
            return offset = 426;
        }

        virtual unsigned int offset427(int) {
            return offset = 427;
        }

        virtual unsigned int offset428(int) {
            return offset = 428;
        }

        virtual unsigned int offset429(int) {
            return offset = 429;
        }

        virtual unsigned int offset430(int) {
            return offset = 430;
        }

        virtual unsigned int offset431(int) {
            return offset = 431;
        }

        virtual unsigned int offset432(int) {
            return offset = 432;
        }

        virtual unsigned int offset433(int) {
            return offset = 433;
        }

        virtual unsigned int offset434(int) {
            return offset = 434;
        }

        virtual unsigned int offset435(int) {
            return offset = 435;
        }

        virtual unsigned int offset436(int) {
            return offset = 436;
        }

        virtual unsigned int offset437(int) {
            return offset = 437;
        }

        virtual unsigned int offset438(int) {
            return offset = 438;
        }

        virtual unsigned int offset439(int) {
            return offset = 439;
        }

        virtual unsigned int offset440(int) {
            return offset = 440;
        }

        virtual unsigned int offset441(int) {
            return offset = 441;
        }

        virtual unsigned int offset442(int) {
            return offset = 442;
        }

        virtual unsigned int offset443(int) {
            return offset = 443;
        }

        virtual unsigned int offset444(int) {
            return offset = 444;
        }

        virtual unsigned int offset445(int) {
            return offset = 445;
        }

        virtual unsigned int offset446(int) {
            return offset = 446;
        }

        virtual unsigned int offset447(int) {
            return offset = 447;
        }

        virtual unsigned int offset448(int) {
            return offset = 448;
        }

        virtual unsigned int offset449(int) {
            return offset = 449;
        }

        virtual unsigned int offset450(int) {
            return offset = 450;
        }

        virtual unsigned int offset451(int) {
            return offset = 451;
        }

        virtual unsigned int offset452(int) {
            return offset = 452;
        }

        virtual unsigned int offset453(int) {
            return offset = 453;
        }

        virtual unsigned int offset454(int) {
            return offset = 454;
        }

        virtual unsigned int offset455(int) {
            return offset = 455;
        }

        virtual unsigned int offset456(int) {
            return offset = 456;
        }

        virtual unsigned int offset457(int) {
            return offset = 457;
        }

        virtual unsigned int offset458(int) {
            return offset = 458;
        }

        virtual unsigned int offset459(int) {
            return offset = 459;
        }

        virtual unsigned int offset460(int) {
            return offset = 460;
        }

        virtual unsigned int offset461(int) {
            return offset = 461;
        }

        virtual unsigned int offset462(int) {
            return offset = 462;
        }

        virtual unsigned int offset463(int) {
            return offset = 463;
        }

        virtual unsigned int offset464(int) {
            return offset = 464;
        }

        virtual unsigned int offset465(int) {
            return offset = 465;
        }

        virtual unsigned int offset466(int) {
            return offset = 466;
        }

        virtual unsigned int offset467(int) {
            return offset = 467;
        }

        virtual unsigned int offset468(int) {
            return offset = 468;
        }

        virtual unsigned int offset469(int) {
            return offset = 469;
        }

        virtual unsigned int offset470(int) {
            return offset = 470;
        }

        virtual unsigned int offset471(int) {
            return offset = 471;
        }

        virtual unsigned int offset472(int) {
            return offset = 472;
        }

        virtual unsigned int offset473(int) {
            return offset = 473;
        }

        virtual unsigned int offset474(int) {
            return offset = 474;
        }

        virtual unsigned int offset475(int) {
            return offset = 475;
        }

        virtual unsigned int offset476(int) {
            return offset = 476;
        }

        virtual unsigned int offset477(int) {
            return offset = 477;
        }

        virtual unsigned int offset478(int) {
            return offset = 478;
        }

        virtual unsigned int offset479(int) {
            return offset = 479;
        }

        virtual unsigned int offset480(int) {
            return offset = 480;
        }

        virtual unsigned int offset481(int) {
            return offset = 481;
        }

        virtual unsigned int offset482(int) {
            return offset = 482;
        }

        virtual unsigned int offset483(int) {
            return offset = 483;
        }

        virtual unsigned int offset484(int) {
            return offset = 484;
        }

        virtual unsigned int offset485(int) {
            return offset = 485;
        }

        virtual unsigned int offset486(int) {
            return offset = 486;
        }

        virtual unsigned int offset487(int) {
            return offset = 487;
        }

        virtual unsigned int offset488(int) {
            return offset = 488;
        }

        virtual unsigned int offset489(int) {
            return offset = 489;
        }

        virtual unsigned int offset490(int) {
            return offset = 490;
        }

        virtual unsigned int offset491(int) {
            return offset = 491;
        }

        virtual unsigned int offset492(int) {
            return offset = 492;
        }

        virtual unsigned int offset493(int) {
            return offset = 493;
        }

        virtual unsigned int offset494(int) {
            return offset = 494;
        }

        virtual unsigned int offset495(int) {
            return offset = 495;
        }

        virtual unsigned int offset496(int) {
            return offset = 496;
        }

        virtual unsigned int offset497(int) {
            return offset = 497;
        }

        virtual unsigned int offset498(int) {
            return offset = 498;
        }

        virtual unsigned int offset499(int) {
            return offset = 499;
        }


        virtual unsigned int offset500(int) {
            return offset = 500;
        }

        virtual unsigned int offset501(int) {
            return offset = 501;
        }

        virtual unsigned int offset502(int) {
            return offset = 502;
        }

        virtual unsigned int offset503(int) {
            return offset = 503;
        }

        virtual unsigned int offset504(int) {
            return offset = 504;
        }

        virtual unsigned int offset505(int) {
            return offset = 505;
        }

        virtual unsigned int offset506(int) {
            return offset = 506;
        }

        virtual unsigned int offset507(int) {
            return offset = 507;
        }

        virtual unsigned int offset508(int) {
            return offset = 508;
        }

        virtual unsigned int offset509(int) {
            return offset = 509;
        }

        virtual unsigned int offset510(int) {
            return offset = 510;
        }

        virtual unsigned int offset511(int) {
            return offset = 511;
        }

        virtual unsigned int offset512(int) {
            return offset = 512;
        }

        virtual unsigned int offset513(int) {
            return offset = 513;
        }

        virtual unsigned int offset514(int) {
            return offset = 514;
        }

        virtual unsigned int offset515(int) {
            return offset = 515;
        }

        virtual unsigned int offset516(int) {
            return offset = 516;
        }

        virtual unsigned int offset517(int) {
            return offset = 517;
        }

        virtual unsigned int offset518(int) {
            return offset = 518;
        }

        virtual unsigned int offset519(int) {
            return offset = 519;
        }

        virtual unsigned int offset520(int) {
            return offset = 520;
        }

        virtual unsigned int offset521(int) {
            return offset = 521;
        }

        virtual unsigned int offset522(int) {
            return offset = 522;
        }

        virtual unsigned int offset523(int) {
            return offset = 523;
        }

        virtual unsigned int offset524(int) {
            return offset = 524;
        }

        virtual unsigned int offset525(int) {
            return offset = 525;
        }

        virtual unsigned int offset526(int) {
            return offset = 526;
        }

        virtual unsigned int offset527(int) {
            return offset = 527;
        }

        virtual unsigned int offset528(int) {
            return offset = 528;
        }

        virtual unsigned int offset529(int) {
            return offset = 529;
        }

        virtual unsigned int offset530(int) {
            return offset = 530;
        }

        virtual unsigned int offset531(int) {
            return offset = 531;
        }

        virtual unsigned int offset532(int) {
            return offset = 532;
        }

        virtual unsigned int offset533(int) {
            return offset = 533;
        }

        virtual unsigned int offset534(int) {
            return offset = 534;
        }

        virtual unsigned int offset535(int) {
            return offset = 535;
        }

        virtual unsigned int offset536(int) {
            return offset = 536;
        }

        virtual unsigned int offset537(int) {
            return offset = 537;
        }

        virtual unsigned int offset538(int) {
            return offset = 538;
        }

        virtual unsigned int offset539(int) {
            return offset = 539;
        }

        virtual unsigned int offset540(int) {
            return offset = 540;
        }

        virtual unsigned int offset541(int) {
            return offset = 541;
        }

        virtual unsigned int offset542(int) {
            return offset = 542;
        }

        virtual unsigned int offset543(int) {
            return offset = 543;
        }

        virtual unsigned int offset544(int) {
            return offset = 544;
        }

        virtual unsigned int offset545(int) {
            return offset = 545;
        }

        virtual unsigned int offset546(int) {
            return offset = 546;
        }

        virtual unsigned int offset547(int) {
            return offset = 547;
        }

        virtual unsigned int offset548(int) {
            return offset = 548;
        }

        virtual unsigned int offset549(int) {
            return offset = 549;
        }

        virtual unsigned int offset550(int) {
            return offset = 550;
        }

        virtual unsigned int offset551(int) {
            return offset = 551;
        }

        virtual unsigned int offset552(int) {
            return offset = 552;
        }

        virtual unsigned int offset553(int) {
            return offset = 553;
        }

        virtual unsigned int offset554(int) {
            return offset = 554;
        }

        virtual unsigned int offset555(int) {
            return offset = 555;
        }

        virtual unsigned int offset556(int) {
            return offset = 556;
        }

        virtual unsigned int offset557(int) {
            return offset = 557;
        }

        virtual unsigned int offset558(int) {
            return offset = 558;
        }

        virtual unsigned int offset559(int) {
            return offset = 559;
        }

        virtual unsigned int offset560(int) {
            return offset = 560;
        }

        virtual unsigned int offset561(int) {
            return offset = 561;
        }

        virtual unsigned int offset562(int) {
            return offset = 562;
        }

        virtual unsigned int offset563(int) {
            return offset = 563;
        }

        virtual unsigned int offset564(int) {
            return offset = 564;
        }

        virtual unsigned int offset565(int) {
            return offset = 565;
        }

        virtual unsigned int offset566(int) {
            return offset = 566;
        }

        virtual unsigned int offset567(int) {
            return offset = 567;
        }

        virtual unsigned int offset568(int) {
            return offset = 568;
        }

        virtual unsigned int offset569(int) {
            return offset = 569;
        }

        virtual unsigned int offset570(int) {
            return offset = 570;
        }

        virtual unsigned int offset571(int) {
            return offset = 571;
        }

        virtual unsigned int offset572(int) {
            return offset = 572;
        }

        virtual unsigned int offset573(int) {
            return offset = 573;
        }

        virtual unsigned int offset574(int) {
            return offset = 574;
        }

        virtual unsigned int offset575(int) {
            return offset = 575;
        }

        virtual unsigned int offset576(int) {
            return offset = 576;
        }

        virtual unsigned int offset577(int) {
            return offset = 577;
        }

        virtual unsigned int offset578(int) {
            return offset = 578;
        }

        virtual unsigned int offset579(int) {
            return offset = 579;
        }

        virtual unsigned int offset580(int) {
            return offset = 580;
        }

        virtual unsigned int offset581(int) {
            return offset = 581;
        }

        virtual unsigned int offset582(int) {
            return offset = 582;
        }

        virtual unsigned int offset583(int) {
            return offset = 583;
        }

        virtual unsigned int offset584(int) {
            return offset = 584;
        }

        virtual unsigned int offset585(int) {
            return offset = 585;
        }

        virtual unsigned int offset586(int) {
            return offset = 586;
        }

        virtual unsigned int offset587(int) {
            return offset = 587;
        }

        virtual unsigned int offset588(int) {
            return offset = 588;
        }

        virtual unsigned int offset589(int) {
            return offset = 589;
        }

        virtual unsigned int offset590(int) {
            return offset = 590;
        }

        virtual unsigned int offset591(int) {
            return offset = 591;
        }

        virtual unsigned int offset592(int) {
            return offset = 592;
        }

        virtual unsigned int offset593(int) {
            return offset = 593;
        }

        virtual unsigned int offset594(int) {
            return offset = 594;
        }

        virtual unsigned int offset595(int) {
            return offset = 595;
        }

        virtual unsigned int offset596(int) {
            return offset = 596;
        }

        virtual unsigned int offset597(int) {
            return offset = 597;
        }

        virtual unsigned int offset598(int) {
            return offset = 598;
        }

        virtual unsigned int offset599(int) {
            return offset = 599;
        }


        virtual unsigned int offset600(int) {
            return offset = 600;
        }

        virtual unsigned int offset601(int) {
            return offset = 601;
        }

        virtual unsigned int offset602(int) {
            return offset = 602;
        }

        virtual unsigned int offset603(int) {
            return offset = 603;
        }

        virtual unsigned int offset604(int) {
            return offset = 604;
        }

        virtual unsigned int offset605(int) {
            return offset = 605;
        }

        virtual unsigned int offset606(int) {
            return offset = 606;
        }

        virtual unsigned int offset607(int) {
            return offset = 607;
        }

        virtual unsigned int offset608(int) {
            return offset = 608;
        }

        virtual unsigned int offset609(int) {
            return offset = 609;
        }

        virtual unsigned int offset610(int) {
            return offset = 610;
        }

        virtual unsigned int offset611(int) {
            return offset = 611;
        }

        virtual unsigned int offset612(int) {
            return offset = 612;
        }

        virtual unsigned int offset613(int) {
            return offset = 613;
        }

        virtual unsigned int offset614(int) {
            return offset = 614;
        }

        virtual unsigned int offset615(int) {
            return offset = 615;
        }

        virtual unsigned int offset616(int) {
            return offset = 616;
        }

        virtual unsigned int offset617(int) {
            return offset = 617;
        }

        virtual unsigned int offset618(int) {
            return offset = 618;
        }

        virtual unsigned int offset619(int) {
            return offset = 619;
        }

        virtual unsigned int offset620(int) {
            return offset = 620;
        }

        virtual unsigned int offset621(int) {
            return offset = 621;
        }

        virtual unsigned int offset622(int) {
            return offset = 622;
        }

        virtual unsigned int offset623(int) {
            return offset = 623;
        }

        virtual unsigned int offset624(int) {
            return offset = 624;
        }

        virtual unsigned int offset625(int) {
            return offset = 625;
        }

        virtual unsigned int offset626(int) {
            return offset = 626;
        }

        virtual unsigned int offset627(int) {
            return offset = 627;
        }

        virtual unsigned int offset628(int) {
            return offset = 628;
        }

        virtual unsigned int offset629(int) {
            return offset = 629;
        }

        virtual unsigned int offset630(int) {
            return offset = 630;
        }

        virtual unsigned int offset631(int) {
            return offset = 631;
        }

        virtual unsigned int offset632(int) {
            return offset = 632;
        }

        virtual unsigned int offset633(int) {
            return offset = 633;
        }

        virtual unsigned int offset634(int) {
            return offset = 634;
        }

        virtual unsigned int offset635(int) {
            return offset = 635;
        }

        virtual unsigned int offset636(int) {
            return offset = 636;
        }

        virtual unsigned int offset637(int) {
            return offset = 637;
        }

        virtual unsigned int offset638(int) {
            return offset = 638;
        }

        virtual unsigned int offset639(int) {
            return offset = 639;
        }

        virtual unsigned int offset640(int) {
            return offset = 640;
        }

        virtual unsigned int offset641(int) {
            return offset = 641;
        }

        virtual unsigned int offset642(int) {
            return offset = 642;
        }

        virtual unsigned int offset643(int) {
            return offset = 643;
        }

        virtual unsigned int offset644(int) {
            return offset = 644;
        }

        virtual unsigned int offset645(int) {
            return offset = 645;
        }

        virtual unsigned int offset646(int) {
            return offset = 646;
        }

        virtual unsigned int offset647(int) {
            return offset = 647;
        }

        virtual unsigned int offset648(int) {
            return offset = 648;
        }

        virtual unsigned int offset649(int) {
            return offset = 649;
        }

        virtual unsigned int offset650(int) {
            return offset = 650;
        }

        virtual unsigned int offset651(int) {
            return offset = 651;
        }

        virtual unsigned int offset652(int) {
            return offset = 652;
        }

        virtual unsigned int offset653(int) {
            return offset = 653;
        }

        virtual unsigned int offset654(int) {
            return offset = 654;
        }

        virtual unsigned int offset655(int) {
            return offset = 655;
        }

        virtual unsigned int offset656(int) {
            return offset = 656;
        }

        virtual unsigned int offset657(int) {
            return offset = 657;
        }

        virtual unsigned int offset658(int) {
            return offset = 658;
        }

        virtual unsigned int offset659(int) {
            return offset = 659;
        }

        virtual unsigned int offset660(int) {
            return offset = 660;
        }

        virtual unsigned int offset661(int) {
            return offset = 661;
        }

        virtual unsigned int offset662(int) {
            return offset = 662;
        }

        virtual unsigned int offset663(int) {
            return offset = 663;
        }

        virtual unsigned int offset664(int) {
            return offset = 664;
        }

        virtual unsigned int offset665(int) {
            return offset = 665;
        }

        virtual unsigned int offset666(int) {
            return offset = 666;
        }

        virtual unsigned int offset667(int) {
            return offset = 667;
        }

        virtual unsigned int offset668(int) {
            return offset = 668;
        }

        virtual unsigned int offset669(int) {
            return offset = 669;
        }

        virtual unsigned int offset670(int) {
            return offset = 670;
        }

        virtual unsigned int offset671(int) {
            return offset = 671;
        }

        virtual unsigned int offset672(int) {
            return offset = 672;
        }

        virtual unsigned int offset673(int) {
            return offset = 673;
        }

        virtual unsigned int offset674(int) {
            return offset = 674;
        }

        virtual unsigned int offset675(int) {
            return offset = 675;
        }

        virtual unsigned int offset676(int) {
            return offset = 676;
        }

        virtual unsigned int offset677(int) {
            return offset = 677;
        }

        virtual unsigned int offset678(int) {
            return offset = 678;
        }

        virtual unsigned int offset679(int) {
            return offset = 679;
        }

        virtual unsigned int offset680(int) {
            return offset = 680;
        }

        virtual unsigned int offset681(int) {
            return offset = 681;
        }

        virtual unsigned int offset682(int) {
            return offset = 682;
        }

        virtual unsigned int offset683(int) {
            return offset = 683;
        }

        virtual unsigned int offset684(int) {
            return offset = 684;
        }

        virtual unsigned int offset685(int) {
            return offset = 685;
        }

        virtual unsigned int offset686(int) {
            return offset = 686;
        }

        virtual unsigned int offset687(int) {
            return offset = 687;
        }

        virtual unsigned int offset688(int) {
            return offset = 688;
        }

        virtual unsigned int offset689(int) {
            return offset = 689;
        }

        virtual unsigned int offset690(int) {
            return offset = 690;
        }

        virtual unsigned int offset691(int) {
            return offset = 691;
        }

        virtual unsigned int offset692(int) {
            return offset = 692;
        }

        virtual unsigned int offset693(int) {
            return offset = 693;
        }

        virtual unsigned int offset694(int) {
            return offset = 694;
        }

        virtual unsigned int offset695(int) {
            return offset = 695;
        }

        virtual unsigned int offset696(int) {
            return offset = 696;
        }

        virtual unsigned int offset697(int) {
            return offset = 697;
        }

        virtual unsigned int offset698(int) {
            return offset = 698;
        }

        virtual unsigned int offset699(int) {
            return offset = 699;
        }


        virtual unsigned int offset700(int) {
            return offset = 700;
        }

        virtual unsigned int offset701(int) {
            return offset = 701;
        }

        virtual unsigned int offset702(int) {
            return offset = 702;
        }

        virtual unsigned int offset703(int) {
            return offset = 703;
        }

        virtual unsigned int offset704(int) {
            return offset = 704;
        }

        virtual unsigned int offset705(int) {
            return offset = 705;
        }

        virtual unsigned int offset706(int) {
            return offset = 706;
        }

        virtual unsigned int offset707(int) {
            return offset = 707;
        }

        virtual unsigned int offset708(int) {
            return offset = 708;
        }

        virtual unsigned int offset709(int) {
            return offset = 709;
        }

        virtual unsigned int offset710(int) {
            return offset = 710;
        }

        virtual unsigned int offset711(int) {
            return offset = 711;
        }

        virtual unsigned int offset712(int) {
            return offset = 712;
        }

        virtual unsigned int offset713(int) {
            return offset = 713;
        }

        virtual unsigned int offset714(int) {
            return offset = 714;
        }

        virtual unsigned int offset715(int) {
            return offset = 715;
        }

        virtual unsigned int offset716(int) {
            return offset = 716;
        }

        virtual unsigned int offset717(int) {
            return offset = 717;
        }

        virtual unsigned int offset718(int) {
            return offset = 718;
        }

        virtual unsigned int offset719(int) {
            return offset = 719;
        }

        virtual unsigned int offset720(int) {
            return offset = 720;
        }

        virtual unsigned int offset721(int) {
            return offset = 721;
        }

        virtual unsigned int offset722(int) {
            return offset = 722;
        }

        virtual unsigned int offset723(int) {
            return offset = 723;
        }

        virtual unsigned int offset724(int) {
            return offset = 724;
        }

        virtual unsigned int offset725(int) {
            return offset = 725;
        }

        virtual unsigned int offset726(int) {
            return offset = 726;
        }

        virtual unsigned int offset727(int) {
            return offset = 727;
        }

        virtual unsigned int offset728(int) {
            return offset = 728;
        }

        virtual unsigned int offset729(int) {
            return offset = 729;
        }

        virtual unsigned int offset730(int) {
            return offset = 730;
        }

        virtual unsigned int offset731(int) {
            return offset = 731;
        }

        virtual unsigned int offset732(int) {
            return offset = 732;
        }

        virtual unsigned int offset733(int) {
            return offset = 733;
        }

        virtual unsigned int offset734(int) {
            return offset = 734;
        }

        virtual unsigned int offset735(int) {
            return offset = 735;
        }

        virtual unsigned int offset736(int) {
            return offset = 736;
        }

        virtual unsigned int offset737(int) {
            return offset = 737;
        }

        virtual unsigned int offset738(int) {
            return offset = 738;
        }

        virtual unsigned int offset739(int) {
            return offset = 739;
        }

        virtual unsigned int offset740(int) {
            return offset = 740;
        }

        virtual unsigned int offset741(int) {
            return offset = 741;
        }

        virtual unsigned int offset742(int) {
            return offset = 742;
        }

        virtual unsigned int offset743(int) {
            return offset = 743;
        }

        virtual unsigned int offset744(int) {
            return offset = 744;
        }

        virtual unsigned int offset745(int) {
            return offset = 745;
        }

        virtual unsigned int offset746(int) {
            return offset = 746;
        }

        virtual unsigned int offset747(int) {
            return offset = 747;
        }

        virtual unsigned int offset748(int) {
            return offset = 748;
        }

        virtual unsigned int offset749(int) {
            return offset = 749;
        }

        virtual unsigned int offset750(int) {
            return offset = 750;
        }

        virtual unsigned int offset751(int) {
            return offset = 751;
        }

        virtual unsigned int offset752(int) {
            return offset = 752;
        }

        virtual unsigned int offset753(int) {
            return offset = 753;
        }

        virtual unsigned int offset754(int) {
            return offset = 754;
        }

        virtual unsigned int offset755(int) {
            return offset = 755;
        }

        virtual unsigned int offset756(int) {
            return offset = 756;
        }

        virtual unsigned int offset757(int) {
            return offset = 757;
        }

        virtual unsigned int offset758(int) {
            return offset = 758;
        }

        virtual unsigned int offset759(int) {
            return offset = 759;
        }

        virtual unsigned int offset760(int) {
            return offset = 760;
        }

        virtual unsigned int offset761(int) {
            return offset = 761;
        }

        virtual unsigned int offset762(int) {
            return offset = 762;
        }

        virtual unsigned int offset763(int) {
            return offset = 763;
        }

        virtual unsigned int offset764(int) {
            return offset = 764;
        }

        virtual unsigned int offset765(int) {
            return offset = 765;
        }

        virtual unsigned int offset766(int) {
            return offset = 766;
        }

        virtual unsigned int offset767(int) {
            return offset = 767;
        }

        virtual unsigned int offset768(int) {
            return offset = 768;
        }

        virtual unsigned int offset769(int) {
            return offset = 769;
        }

        virtual unsigned int offset770(int) {
            return offset = 770;
        }

        virtual unsigned int offset771(int) {
            return offset = 771;
        }

        virtual unsigned int offset772(int) {
            return offset = 772;
        }

        virtual unsigned int offset773(int) {
            return offset = 773;
        }

        virtual unsigned int offset774(int) {
            return offset = 774;
        }

        virtual unsigned int offset775(int) {
            return offset = 775;
        }

        virtual unsigned int offset776(int) {
            return offset = 776;
        }

        virtual unsigned int offset777(int) {
            return offset = 777;
        }

        virtual unsigned int offset778(int) {
            return offset = 778;
        }

        virtual unsigned int offset779(int) {
            return offset = 779;
        }

        virtual unsigned int offset780(int) {
            return offset = 780;
        }

        virtual unsigned int offset781(int) {
            return offset = 781;
        }

        virtual unsigned int offset782(int) {
            return offset = 782;
        }

        virtual unsigned int offset783(int) {
            return offset = 783;
        }

        virtual unsigned int offset784(int) {
            return offset = 784;
        }

        virtual unsigned int offset785(int) {
            return offset = 785;
        }

        virtual unsigned int offset786(int) {
            return offset = 786;
        }

        virtual unsigned int offset787(int) {
            return offset = 787;
        }

        virtual unsigned int offset788(int) {
            return offset = 788;
        }

        virtual unsigned int offset789(int) {
            return offset = 789;
        }

        virtual unsigned int offset790(int) {
            return offset = 790;
        }

        virtual unsigned int offset791(int) {
            return offset = 791;
        }

        virtual unsigned int offset792(int) {
            return offset = 792;
        }

        virtual unsigned int offset793(int) {
            return offset = 793;
        }

        virtual unsigned int offset794(int) {
            return offset = 794;
        }

        virtual unsigned int offset795(int) {
            return offset = 795;
        }

        virtual unsigned int offset796(int) {
            return offset = 796;
        }

        virtual unsigned int offset797(int) {
            return offset = 797;
        }

        virtual unsigned int offset798(int) {
            return offset = 798;
        }

        virtual unsigned int offset799(int) {
            return offset = 799;
        }


        virtual unsigned int offset800(int) {
            return offset = 800;
        }

        virtual unsigned int offset801(int) {
            return offset = 801;
        }

        virtual unsigned int offset802(int) {
            return offset = 802;
        }

        virtual unsigned int offset803(int) {
            return offset = 803;
        }

        virtual unsigned int offset804(int) {
            return offset = 804;
        }

        virtual unsigned int offset805(int) {
            return offset = 805;
        }

        virtual unsigned int offset806(int) {
            return offset = 806;
        }

        virtual unsigned int offset807(int) {
            return offset = 807;
        }

        virtual unsigned int offset808(int) {
            return offset = 808;
        }

        virtual unsigned int offset809(int) {
            return offset = 809;
        }

        virtual unsigned int offset810(int) {
            return offset = 810;
        }

        virtual unsigned int offset811(int) {
            return offset = 811;
        }

        virtual unsigned int offset812(int) {
            return offset = 812;
        }

        virtual unsigned int offset813(int) {
            return offset = 813;
        }

        virtual unsigned int offset814(int) {
            return offset = 814;
        }

        virtual unsigned int offset815(int) {
            return offset = 815;
        }

        virtual unsigned int offset816(int) {
            return offset = 816;
        }

        virtual unsigned int offset817(int) {
            return offset = 817;
        }

        virtual unsigned int offset818(int) {
            return offset = 818;
        }

        virtual unsigned int offset819(int) {
            return offset = 819;
        }

        virtual unsigned int offset820(int) {
            return offset = 820;
        }

        virtual unsigned int offset821(int) {
            return offset = 821;
        }

        virtual unsigned int offset822(int) {
            return offset = 822;
        }

        virtual unsigned int offset823(int) {
            return offset = 823;
        }

        virtual unsigned int offset824(int) {
            return offset = 824;
        }

        virtual unsigned int offset825(int) {
            return offset = 825;
        }

        virtual unsigned int offset826(int) {
            return offset = 826;
        }

        virtual unsigned int offset827(int) {
            return offset = 827;
        }

        virtual unsigned int offset828(int) {
            return offset = 828;
        }

        virtual unsigned int offset829(int) {
            return offset = 829;
        }

        virtual unsigned int offset830(int) {
            return offset = 830;
        }

        virtual unsigned int offset831(int) {
            return offset = 831;
        }

        virtual unsigned int offset832(int) {
            return offset = 832;
        }

        virtual unsigned int offset833(int) {
            return offset = 833;
        }

        virtual unsigned int offset834(int) {
            return offset = 834;
        }

        virtual unsigned int offset835(int) {
            return offset = 835;
        }

        virtual unsigned int offset836(int) {
            return offset = 836;
        }

        virtual unsigned int offset837(int) {
            return offset = 837;
        }

        virtual unsigned int offset838(int) {
            return offset = 838;
        }

        virtual unsigned int offset839(int) {
            return offset = 839;
        }

        virtual unsigned int offset840(int) {
            return offset = 840;
        }

        virtual unsigned int offset841(int) {
            return offset = 841;
        }

        virtual unsigned int offset842(int) {
            return offset = 842;
        }

        virtual unsigned int offset843(int) {
            return offset = 843;
        }

        virtual unsigned int offset844(int) {
            return offset = 844;
        }

        virtual unsigned int offset845(int) {
            return offset = 845;
        }

        virtual unsigned int offset846(int) {
            return offset = 846;
        }

        virtual unsigned int offset847(int) {
            return offset = 847;
        }

        virtual unsigned int offset848(int) {
            return offset = 848;
        }

        virtual unsigned int offset849(int) {
            return offset = 849;
        }

        virtual unsigned int offset850(int) {
            return offset = 850;
        }

        virtual unsigned int offset851(int) {
            return offset = 851;
        }

        virtual unsigned int offset852(int) {
            return offset = 852;
        }

        virtual unsigned int offset853(int) {
            return offset = 853;
        }

        virtual unsigned int offset854(int) {
            return offset = 854;
        }

        virtual unsigned int offset855(int) {
            return offset = 855;
        }

        virtual unsigned int offset856(int) {
            return offset = 856;
        }

        virtual unsigned int offset857(int) {
            return offset = 857;
        }

        virtual unsigned int offset858(int) {
            return offset = 858;
        }

        virtual unsigned int offset859(int) {
            return offset = 859;
        }

        virtual unsigned int offset860(int) {
            return offset = 860;
        }

        virtual unsigned int offset861(int) {
            return offset = 861;
        }

        virtual unsigned int offset862(int) {
            return offset = 862;
        }

        virtual unsigned int offset863(int) {
            return offset = 863;
        }

        virtual unsigned int offset864(int) {
            return offset = 864;
        }

        virtual unsigned int offset865(int) {
            return offset = 865;
        }

        virtual unsigned int offset866(int) {
            return offset = 866;
        }

        virtual unsigned int offset867(int) {
            return offset = 867;
        }

        virtual unsigned int offset868(int) {
            return offset = 868;
        }

        virtual unsigned int offset869(int) {
            return offset = 869;
        }

        virtual unsigned int offset870(int) {
            return offset = 870;
        }

        virtual unsigned int offset871(int) {
            return offset = 871;
        }

        virtual unsigned int offset872(int) {
            return offset = 872;
        }

        virtual unsigned int offset873(int) {
            return offset = 873;
        }

        virtual unsigned int offset874(int) {
            return offset = 874;
        }

        virtual unsigned int offset875(int) {
            return offset = 875;
        }

        virtual unsigned int offset876(int) {
            return offset = 876;
        }

        virtual unsigned int offset877(int) {
            return offset = 877;
        }

        virtual unsigned int offset878(int) {
            return offset = 878;
        }

        virtual unsigned int offset879(int) {
            return offset = 879;
        }

        virtual unsigned int offset880(int) {
            return offset = 880;
        }

        virtual unsigned int offset881(int) {
            return offset = 881;
        }

        virtual unsigned int offset882(int) {
            return offset = 882;
        }

        virtual unsigned int offset883(int) {
            return offset = 883;
        }

        virtual unsigned int offset884(int) {
            return offset = 884;
        }

        virtual unsigned int offset885(int) {
            return offset = 885;
        }

        virtual unsigned int offset886(int) {
            return offset = 886;
        }

        virtual unsigned int offset887(int) {
            return offset = 887;
        }

        virtual unsigned int offset888(int) {
            return offset = 888;
        }

        virtual unsigned int offset889(int) {
            return offset = 889;
        }

        virtual unsigned int offset890(int) {
            return offset = 890;
        }

        virtual unsigned int offset891(int) {
            return offset = 891;
        }

        virtual unsigned int offset892(int) {
            return offset = 892;
        }

        virtual unsigned int offset893(int) {
            return offset = 893;
        }

        virtual unsigned int offset894(int) {
            return offset = 894;
        }

        virtual unsigned int offset895(int) {
            return offset = 895;
        }

        virtual unsigned int offset896(int) {
            return offset = 896;
        }

        virtual unsigned int offset897(int) {
            return offset = 897;
        }

        virtual unsigned int offset898(int) {
            return offset = 898;
        }

        virtual unsigned int offset899(int) {
            return offset = 899;
        }


        virtual unsigned int offset900(int) {
            return offset = 900;
        }

        virtual unsigned int offset901(int) {
            return offset = 901;
        }

        virtual unsigned int offset902(int) {
            return offset = 902;
        }

        virtual unsigned int offset903(int) {
            return offset = 903;
        }

        virtual unsigned int offset904(int) {
            return offset = 904;
        }

        virtual unsigned int offset905(int) {
            return offset = 905;
        }

        virtual unsigned int offset906(int) {
            return offset = 906;
        }

        virtual unsigned int offset907(int) {
            return offset = 907;
        }

        virtual unsigned int offset908(int) {
            return offset = 908;
        }

        virtual unsigned int offset909(int) {
            return offset = 909;
        }

        virtual unsigned int offset910(int) {
            return offset = 910;
        }

        virtual unsigned int offset911(int) {
            return offset = 911;
        }

        virtual unsigned int offset912(int) {
            return offset = 912;
        }

        virtual unsigned int offset913(int) {
            return offset = 913;
        }

        virtual unsigned int offset914(int) {
            return offset = 914;
        }

        virtual unsigned int offset915(int) {
            return offset = 915;
        }

        virtual unsigned int offset916(int) {
            return offset = 916;
        }

        virtual unsigned int offset917(int) {
            return offset = 917;
        }

        virtual unsigned int offset918(int) {
            return offset = 918;
        }

        virtual unsigned int offset919(int) {
            return offset = 919;
        }

        virtual unsigned int offset920(int) {
            return offset = 920;
        }

        virtual unsigned int offset921(int) {
            return offset = 921;
        }

        virtual unsigned int offset922(int) {
            return offset = 922;
        }

        virtual unsigned int offset923(int) {
            return offset = 923;
        }

        virtual unsigned int offset924(int) {
            return offset = 924;
        }

        virtual unsigned int offset925(int) {
            return offset = 925;
        }

        virtual unsigned int offset926(int) {
            return offset = 926;
        }

        virtual unsigned int offset927(int) {
            return offset = 927;
        }

        virtual unsigned int offset928(int) {
            return offset = 928;
        }

        virtual unsigned int offset929(int) {
            return offset = 929;
        }

        virtual unsigned int offset930(int) {
            return offset = 930;
        }

        virtual unsigned int offset931(int) {
            return offset = 931;
        }

        virtual unsigned int offset932(int) {
            return offset = 932;
        }

        virtual unsigned int offset933(int) {
            return offset = 933;
        }

        virtual unsigned int offset934(int) {
            return offset = 934;
        }

        virtual unsigned int offset935(int) {
            return offset = 935;
        }

        virtual unsigned int offset936(int) {
            return offset = 936;
        }

        virtual unsigned int offset937(int) {
            return offset = 937;
        }

        virtual unsigned int offset938(int) {
            return offset = 938;
        }

        virtual unsigned int offset939(int) {
            return offset = 939;
        }

        virtual unsigned int offset940(int) {
            return offset = 940;
        }

        virtual unsigned int offset941(int) {
            return offset = 941;
        }

        virtual unsigned int offset942(int) {
            return offset = 942;
        }

        virtual unsigned int offset943(int) {
            return offset = 943;
        }

        virtual unsigned int offset944(int) {
            return offset = 944;
        }

        virtual unsigned int offset945(int) {
            return offset = 945;
        }

        virtual unsigned int offset946(int) {
            return offset = 946;
        }

        virtual unsigned int offset947(int) {
            return offset = 947;
        }

        virtual unsigned int offset948(int) {
            return offset = 948;
        }

        virtual unsigned int offset949(int) {
            return offset = 949;
        }

        virtual unsigned int offset950(int) {
            return offset = 950;
        }

        virtual unsigned int offset951(int) {
            return offset = 951;
        }

        virtual unsigned int offset952(int) {
            return offset = 952;
        }

        virtual unsigned int offset953(int) {
            return offset = 953;
        }

        virtual unsigned int offset954(int) {
            return offset = 954;
        }

        virtual unsigned int offset955(int) {
            return offset = 955;
        }

        virtual unsigned int offset956(int) {
            return offset = 956;
        }

        virtual unsigned int offset957(int) {
            return offset = 957;
        }

        virtual unsigned int offset958(int) {
            return offset = 958;
        }

        virtual unsigned int offset959(int) {
            return offset = 959;
        }

        virtual unsigned int offset960(int) {
            return offset = 960;
        }

        virtual unsigned int offset961(int) {
            return offset = 961;
        }

        virtual unsigned int offset962(int) {
            return offset = 962;
        }

        virtual unsigned int offset963(int) {
            return offset = 963;
        }

        virtual unsigned int offset964(int) {
            return offset = 964;
        }

        virtual unsigned int offset965(int) {
            return offset = 965;
        }

        virtual unsigned int offset966(int) {
            return offset = 966;
        }

        virtual unsigned int offset967(int) {
            return offset = 967;
        }

        virtual unsigned int offset968(int) {
            return offset = 968;
        }

        virtual unsigned int offset969(int) {
            return offset = 969;
        }

        virtual unsigned int offset970(int) {
            return offset = 970;
        }

        virtual unsigned int offset971(int) {
            return offset = 971;
        }

        virtual unsigned int offset972(int) {
            return offset = 972;
        }

        virtual unsigned int offset973(int) {
            return offset = 973;
        }

        virtual unsigned int offset974(int) {
            return offset = 974;
        }

        virtual unsigned int offset975(int) {
            return offset = 975;
        }

        virtual unsigned int offset976(int) {
            return offset = 976;
        }

        virtual unsigned int offset977(int) {
            return offset = 977;
        }

        virtual unsigned int offset978(int) {
            return offset = 978;
        }

        virtual unsigned int offset979(int) {
            return offset = 979;
        }

        virtual unsigned int offset980(int) {
            return offset = 980;
        }

        virtual unsigned int offset981(int) {
            return offset = 981;
        }

        virtual unsigned int offset982(int) {
            return offset = 982;
        }

        virtual unsigned int offset983(int) {
            return offset = 983;
        }

        virtual unsigned int offset984(int) {
            return offset = 984;
        }

        virtual unsigned int offset985(int) {
            return offset = 985;
        }

        virtual unsigned int offset986(int) {
            return offset = 986;
        }

        virtual unsigned int offset987(int) {
            return offset = 987;
        }

        virtual unsigned int offset988(int) {
            return offset = 988;
        }

        virtual unsigned int offset989(int) {
            return offset = 989;
        }

        virtual unsigned int offset990(int) {
            return offset = 990;
        }

        virtual unsigned int offset991(int) {
            return offset = 991;
        }

        virtual unsigned int offset992(int) {
            return offset = 992;
        }

        virtual unsigned int offset993(int) {
            return offset = 993;
        }

        virtual unsigned int offset994(int) {
            return offset = 994;
        }

        virtual unsigned int offset995(int) {
            return offset = 995;
        }

        virtual unsigned int offset996(int) {
            return offset = 996;
        }

        virtual unsigned int offset997(int) {
            return offset = 997;
        }

        virtual unsigned int offset998(int) {
            return offset = 998;
        }

        virtual unsigned int offset999(int) {
            return offset = 999;
        }

        virtual unsigned int offset1000(int) {
            return offset = 1000;
        }

    };
}
namespace fakeit {

    template<typename TARGET, typename SOURCE>
    TARGET union_cast(SOURCE source) {

        union {
            SOURCE source;
            TARGET target;
        } u;
        u.source = source;
        return u.target;
    }

}

namespace fakeit {
    class NoVirtualDtor : public std::runtime_error {
    public:
		NoVirtualDtor() :std::runtime_error("Can't mock the destructor. No virtual destructor was found") {}
    };

    class VTUtils {
    public:

        template<typename C, typename R, typename ... arglist>
        static unsigned int getOffset(R (C::*vMethod)(arglist...)) {
            auto sMethod = reinterpret_cast<unsigned int (VirtualOffsetSelector::*)(int)>(vMethod);
            VirtualOffsetSelector offsetSelctor;
            return (offsetSelctor.*sMethod)(0);
        }

        template<typename C>
        static typename std::enable_if<std::has_virtual_destructor<C>::value, unsigned int>::type
        getDestructorOffset() {
            VirtualOffsetSelector offsetSelctor;
            union_cast<C *>(&offsetSelctor)->~C();
            return offsetSelctor.offset;
        }

        template<typename C>
        static typename std::enable_if<!std::has_virtual_destructor<C>::value, unsigned int>::type
        getDestructorOffset() {
            throw NoVirtualDtor();
        }

		template<typename C>
		static typename std::enable_if<std::has_virtual_destructor<C>::value, bool>::type
			hasVirtualDestructor() {
			return true;
		}

		template<typename C>
		static typename std::enable_if<!std::has_virtual_destructor<C>::value, bool>::type
			hasVirtualDestructor() {
			return false;
		}

        template<typename C>
        static unsigned int getVTSize() {
            struct Derrived : public C {
                virtual void endOfVt() {
                }
            };

            unsigned int vtSize = getOffset(&Derrived::endOfVt);
            return vtSize;
        }
    };


}
#ifdef _MSC_VER
namespace fakeit {

    typedef unsigned long dword_;

    struct TypeDescriptor {
        TypeDescriptor() :
                ptrToVTable(0), spare(0) {

            int **tiVFTPtr = (int **) (&typeid(void));
            int *i = (int *) tiVFTPtr[0];
			char *type_info_vft_ptr = (char *) i;
            ptrToVTable = type_info_vft_ptr;
        }

		char *ptrToVTable;
        dword_ spare;
        char name[8];
    };

    struct PMD {



        int mdisp;

        int pdisp;
        int vdisp;

        PMD() :
                mdisp(0), pdisp(-1), vdisp(0) {
        }
    };

    struct RTTIBaseClassDescriptor {
        RTTIBaseClassDescriptor() :
                pTypeDescriptor(nullptr), numContainedBases(0), attributes(0) {
        }

        const std::type_info *pTypeDescriptor;
        dword_ numContainedBases;
        struct PMD where;
        dword_ attributes;
    };

    template<typename C, typename... baseclasses>
    struct RTTIClassHierarchyDescriptor {
        RTTIClassHierarchyDescriptor() :
                signature(0),
                attributes(0),
                numBaseClasses(0),
                pBaseClassArray(nullptr) {
            pBaseClassArray = new RTTIBaseClassDescriptor *[1 + sizeof...(baseclasses)];
            addBaseClass < C, baseclasses...>();
        }

        ~RTTIClassHierarchyDescriptor() {
            for (int i = 0; i < 1 + sizeof...(baseclasses); i++) {
                RTTIBaseClassDescriptor *desc = pBaseClassArray[i];
                delete desc;
            }
            delete[] pBaseClassArray;
        }

        dword_ signature;
        dword_ attributes;
        dword_ numBaseClasses;
        RTTIBaseClassDescriptor **pBaseClassArray;

        template<typename BaseType>
        void addBaseClass() {
            static_assert(std::is_base_of<BaseType, C>::value, "C must be a derived class of BaseType");
            RTTIBaseClassDescriptor *desc = new RTTIBaseClassDescriptor();
            desc->pTypeDescriptor = &typeid(BaseType);
            pBaseClassArray[numBaseClasses] = desc;
            for (unsigned int i = 0; i < numBaseClasses; i++) {
                pBaseClassArray[i]->numContainedBases++;
            }
            numBaseClasses++;
        }

        template<typename head, typename B1, typename... tail>
        void addBaseClass() {
            static_assert(std::is_base_of<B1, head>::value, "invalid inheritance list");
            addBaseClass<head>();
            addBaseClass<B1, tail...>();
        }

    };

	template<typename C, typename... baseclasses>
	struct RTTICompleteObjectLocator {
#ifdef _WIN64
		RTTICompleteObjectLocator(const std::type_info &unused) :
			signature(0), offset(0), cdOffset(0),
			typeDescriptorOffset(0), classDescriptorOffset(0)
		{
		}

		dword_ signature;
		dword_ offset;
		dword_ cdOffset;
		dword_ typeDescriptorOffset;
		dword_ classDescriptorOffset;
#else
		RTTICompleteObjectLocator(const std::type_info &info) :
			signature(0), offset(0), cdOffset(0),
			pTypeDescriptor(&info),
			pClassDescriptor(new RTTIClassHierarchyDescriptor<C, baseclasses...>()) {
		}

		~RTTICompleteObjectLocator() {
			delete pClassDescriptor;
		}

		dword_ signature;
		dword_ offset;
		dword_ cdOffset;
		const std::type_info *pTypeDescriptor;
		struct RTTIClassHierarchyDescriptor<C, baseclasses...> *pClassDescriptor;
#endif
	};


    struct VirtualTableBase {

        static VirtualTableBase &getVTable(void *instance) {
            fakeit::VirtualTableBase *vt = (fakeit::VirtualTableBase *) (instance);
            return *vt;
        }

        VirtualTableBase(void **firstMethod) : _firstMethod(firstMethod) { }

        void *getCookie(int index) {
            return _firstMethod[-2 - index];
        }

        void setCookie(int index, void *value) {
            _firstMethod[-2 - index] = value;
        }

        void *getMethod(unsigned int index) const {
            return _firstMethod[index];
        }

        void setMethod(unsigned int index, void *method) {
            _firstMethod[index] = method;
        }

    protected:
        void **_firstMethod;
    };

    template<class C, class... baseclasses>
    struct VirtualTable : public VirtualTableBase {

        class Handle {

            friend struct VirtualTable<C, baseclasses...>;

            void **firstMethod;

            Handle(void **method) : firstMethod(method) { }

        public:

            VirtualTable<C, baseclasses...> &restore() {
                VirtualTable<C, baseclasses...> *vt = (VirtualTable<C, baseclasses...> *) this;
                return *vt;
            }
        };

        static VirtualTable<C, baseclasses...> &getVTable(C &instance) {
            fakeit::VirtualTable<C, baseclasses...> *vt = (fakeit::VirtualTable<C, baseclasses...> *) (&instance);
            return *vt;
        }

        void copyFrom(VirtualTable<C, baseclasses...> &from) {
            unsigned int size = VTUtils::getVTSize<C>();
            for (unsigned int i = 0; i < size; i++) {
                _firstMethod[i] = from.getMethod(i);
            }
        }

        VirtualTable() : VirtualTable(buildVTArray()) {
        }

        ~VirtualTable() {

        }

        void dispose() {
            _firstMethod--;
            RTTICompleteObjectLocator<C, baseclasses...> *locator = (RTTICompleteObjectLocator<C, baseclasses...> *) _firstMethod[0];
            delete locator;
            _firstMethod -= numOfCookies;
            delete[] _firstMethod;
        }


        unsigned int dtor(int) {
            C *c = (C *) this;
            C &cRef = *c;
            auto vt = VirtualTable<C, baseclasses...>::getVTable(cRef);
            void *dtorPtr = vt.getCookie(numOfCookies - 1);
            void(*method)(C *) = reinterpret_cast<void (*)(C *)>(dtorPtr);
            method(c);
            return 0;
        }

        void setDtor(void *method) {





            void *dtorPtr = union_cast<void *>(&VirtualTable<C, baseclasses...>::dtor);
            unsigned int index = VTUtils::getDestructorOffset<C>();
            _firstMethod[index] = dtorPtr;
            setCookie(numOfCookies - 1, method);
        }

        unsigned int getSize() {
            return VTUtils::getVTSize<C>();
        }

        void initAll(void *value) {
            auto size = getSize();
            for (unsigned int i = 0; i < size; i++) {
                setMethod(i, value);
            }
        }

        Handle createHandle() {
            Handle h(_firstMethod);
            return h;
        }

    private:

        class SimpleType {
        };

        static_assert(sizeof(unsigned int (SimpleType::*)()) == sizeof(unsigned int (C::*)()),
            "Can't mock a type with multiple inheritance or with non-polymorphic base class");
        static const unsigned int numOfCookies = 3;

        static void **buildVTArray() {
            int vtSize = VTUtils::getVTSize<C>();
            auto array = new void *[vtSize + numOfCookies + 1]{};
            RTTICompleteObjectLocator<C, baseclasses...> *objectLocator = new RTTICompleteObjectLocator<C, baseclasses...>(
                    typeid(C));
            array += numOfCookies;
            array[0] = objectLocator;
            array++;
            return array;
        }

        VirtualTable(void **firstMethod) : VirtualTableBase(firstMethod) {
        }
    };
}
#else
#ifndef __clang__
#include <type_traits>
#include <tr2/type_traits>

namespace fakeit {
    template<typename ... T1>
    class has_one_base {
    };

    template<typename T1, typename T2, typename ... types>
    class has_one_base<std::tr2::__reflection_typelist<T1, T2, types...>> : public std::false_type {
    };

    template<typename T1>
    class has_one_base<std::tr2::__reflection_typelist<T1>>
            : public has_one_base<typename std::tr2::direct_bases<T1>::type> {
    };

    template<>
    class has_one_base<std::tr2::__reflection_typelist<>> : public std::true_type {
    };

    template<typename T>
    class is_simple_inheritance_layout : public has_one_base<typename std::tr2::direct_bases<T>::type> {
    };
}

#endif

namespace fakeit {

    struct VirtualTableBase {

        static VirtualTableBase &getVTable(void *instance) {
            fakeit::VirtualTableBase *vt = (fakeit::VirtualTableBase *) (instance);
            return *vt;
        }

        VirtualTableBase(void **firstMethod) : _firstMethod(firstMethod) { }

        void *getCookie(int index) {
            return _firstMethod[-3 - index];
        }

        void setCookie(int index, void *value) {
            _firstMethod[-3 - index] = value;
        }

        void *getMethod(unsigned int index) const {
            return _firstMethod[index];
        }

        void setMethod(unsigned int index, void *method) {
            _firstMethod[index] = method;
        }

    protected:
        void **_firstMethod;
    };

    template<class C, class ... baseclasses>
    struct VirtualTable : public VirtualTableBase {

#ifndef __clang__
        static_assert(is_simple_inheritance_layout<C>::value, "Can't mock a type with multiple inheritance");
#endif

        class Handle {

            friend struct VirtualTable<C, baseclasses...>;
            void **firstMethod;

            Handle(void **method) :
                    firstMethod(method) {
            }

        public:

            VirtualTable<C, baseclasses...> &restore() {
                VirtualTable<C, baseclasses...> *vt = (VirtualTable<C, baseclasses...> *) this;
                return *vt;
            }
        };

        static VirtualTable<C, baseclasses...> &getVTable(C &instance) {
            fakeit::VirtualTable<C, baseclasses...> *vt = (fakeit::VirtualTable<C, baseclasses...> *) (&instance);
            return *vt;
        }

        void copyFrom(VirtualTable<C, baseclasses...> &from) {
            unsigned int size = VTUtils::getVTSize<C>();

            for (size_t i = 0; i < size; ++i) {
                _firstMethod[i] = from.getMethod(i);
            }
        }

        VirtualTable() :
                VirtualTable(buildVTArray()) {
        }

        void dispose() {
            _firstMethod--;
            _firstMethod--;
            _firstMethod -= numOfCookies;
            delete[] _firstMethod;
        }

        unsigned int dtor(int) {
            C *c = (C *) this;
            C &cRef = *c;
            auto vt = VirtualTable<C, baseclasses...>::getVTable(cRef);
            unsigned int index = VTUtils::getDestructorOffset<C>();
            void *dtorPtr = vt.getMethod(index);
            void(*method)(C *) = union_cast<void (*)(C *)>(dtorPtr);
            method(c);
            return 0;
        }


        void setDtor(void *method) {
            unsigned int index = VTUtils::getDestructorOffset<C>();
            void *dtorPtr = union_cast<void *>(&VirtualTable<C, baseclasses...>::dtor);


            _firstMethod[index] = method;

            _firstMethod[index + 1] = dtorPtr;
        }


        unsigned int getSize() {
            return VTUtils::getVTSize<C>();
        }

        void initAll(void *value) {
            unsigned int size = getSize();
            for (unsigned int i = 0; i < size; i++) {
                setMethod(i, value);
            }
        }

        const std::type_info *getTypeId() {
            return (const std::type_info *) (_firstMethod[-1]);
        }

        Handle createHandle() {
            Handle h(_firstMethod);
            return h;
        }

    private:
        static const unsigned int numOfCookies = 2;

        static void **buildVTArray() {
            int size = VTUtils::getVTSize<C>();
            auto array = new void *[size + 2 + numOfCookies]{};
            array += numOfCookies;
            array++;
            array[0] = const_cast<std::type_info *>(&typeid(C));
            array++;
            return array;
        }

        VirtualTable(void **firstMethod) : VirtualTableBase(firstMethod) {
        }

    };
}
#endif
namespace fakeit {

    struct NoMoreRecordedActionException {
    };

    template<typename R, typename ... arglist>
    struct MethodInvocationHandler : Destructible {
        virtual R handleMethodInvocation(const typename fakeit::production_arg<arglist>::type... args) = 0;
    };

}
#include <new>

namespace fakeit {

#ifdef __GNUG__
#ifndef __clang__
#pragma GCC diagnostic ignored "-Wpedantic"
#endif
#endif


#ifdef _MSC_VER
#pragma warning( push )
#pragma warning( disable : 4200 )
#endif


    template<typename C, typename ... baseclasses>
    class FakeObject {

        VirtualTable<C, baseclasses...> vtable;

        static const size_t SIZE = sizeof(C) - sizeof(VirtualTable<C, baseclasses...>);
        char instanceArea[SIZE ? SIZE : 0];

        FakeObject(FakeObject const &) = delete;
        FakeObject &operator=(FakeObject const &) = delete;

    public:

        FakeObject() : vtable() {
            initializeDataMembersArea();
        }

        ~FakeObject() {
            vtable.dispose();
        }

        void initializeDataMembersArea() {
            for (size_t i = 0; i < SIZE; ++i) instanceArea[i] = (char) 0;
        }

        void setMethod(unsigned int index, void *method) {
            vtable.setMethod(index, method);
        }

        VirtualTable<C, baseclasses...> &getVirtualTable() {
            return vtable;
        }

        void setVirtualTable(VirtualTable<C, baseclasses...> &t) {
            vtable = t;
        }

        void setDtor(void *dtor) {
            vtable.setDtor(dtor);
        }
    };

#ifdef _MSC_VER
#pragma warning( pop )
#endif

#ifdef __GNUG__
#ifndef __clang__
#pragma GCC diagnostic pop
#endif
#endif

}
namespace fakeit {

    struct MethodProxy {

        MethodProxy(unsigned int id, unsigned int offset, void *vMethod) :
                _id(id),
                _offset(offset),
                _vMethod(vMethod) {
        }

        unsigned int getOffset() const {
            return _offset;
        }

        unsigned int getId() const {
            return _id;
        }

        void *getProxy() const {
            return union_cast<void *>(_vMethod);
        }

    private:
        unsigned int _id;
        unsigned int _offset;
        void *_vMethod;
    };
}
#include <utility>


namespace fakeit {

    struct InvocationHandlerCollection {
        static const unsigned int VT_COOKIE_INDEX = 0;

        virtual Destructible *getInvocatoinHandlerPtrById(unsigned int index) = 0;

        static InvocationHandlerCollection *getInvocationHandlerCollection(void *instance) {
            VirtualTableBase &vt = VirtualTableBase::getVTable(instance);
            InvocationHandlerCollection *invocationHandlerCollection = (InvocationHandlerCollection *) vt.getCookie(
                    InvocationHandlerCollection::VT_COOKIE_INDEX);
            return invocationHandlerCollection;
        }
    };


    template<typename R, typename ... arglist>
    class MethodProxyCreator {



    public:

        template<unsigned int id>
        MethodProxy createMethodProxy(unsigned int offset) {
            return MethodProxy(id, offset, union_cast<void *>(&MethodProxyCreator::methodProxyX < id > ));
        }

    protected:

        R methodProxy(unsigned int id, const typename fakeit::production_arg<arglist>::type... args) {
            InvocationHandlerCollection *invocationHandlerCollection = InvocationHandlerCollection::getInvocationHandlerCollection(
                    this);
            MethodInvocationHandler<R, arglist...> *invocationHandler =
                    (MethodInvocationHandler<R, arglist...> *) invocationHandlerCollection->getInvocatoinHandlerPtrById(
                            id);
            return invocationHandler->handleMethodInvocation(std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
        }

        template<int id>
        R methodProxyX(arglist ... args) {
            return methodProxy(id, std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);
        }
    };
}

namespace fakeit {

    class InvocationHandlers : public InvocationHandlerCollection {
        std::vector<std::shared_ptr<Destructible>> &_methodMocks;
        std::vector<unsigned int> &_offsets;

        unsigned int getOffset(unsigned int id) const
        {
            unsigned int offset = 0;
            for (; offset < _offsets.size(); offset++) {
                if (_offsets[offset] == id) {
                    break;
                }
            }
            return offset;
        }

    public:
        InvocationHandlers(
                std::vector<std::shared_ptr<Destructible>> &methodMocks,
                std::vector<unsigned int> &offsets) :
                _methodMocks(methodMocks), _offsets(offsets) {
			for (std::vector<unsigned int>::iterator it = _offsets.begin(); it != _offsets.end(); ++it)
			{
				*it = std::numeric_limits<int>::max();
			}
        }

        Destructible *getInvocatoinHandlerPtrById(unsigned int id) override {
            unsigned int offset = getOffset(id);
            std::shared_ptr<Destructible> ptr = _methodMocks[offset];
            return ptr.get();
        }

    };

    template<typename C, typename ... baseclasses>
    struct DynamicProxy {

        static_assert(std::is_polymorphic<C>::value, "DynamicProxy requires a polymorphic type");

        DynamicProxy(C &inst) :
                instance(inst),
                originalVtHandle(VirtualTable<C, baseclasses...>::getVTable(instance).createHandle()),
                _methodMocks(VTUtils::getVTSize<C>()),
                _offsets(VTUtils::getVTSize<C>()),
                _invocationHandlers(_methodMocks, _offsets) {
            _cloneVt.copyFrom(originalVtHandle.restore());
            _cloneVt.setCookie(InvocationHandlerCollection::VT_COOKIE_INDEX, &_invocationHandlers);
            getFake().setVirtualTable(_cloneVt);
        }

        void detach() {
            getFake().setVirtualTable(originalVtHandle.restore());
        }

        ~DynamicProxy() {
            _cloneVt.dispose();
        }

        C &get() {
            return instance;
        }

        void Reset() {
			_methodMocks = {};
            _methodMocks.resize(VTUtils::getVTSize<C>());
            _members = {};
			_offsets = {};
            _offsets.resize(VTUtils::getVTSize<C>());
            _cloneVt.copyFrom(originalVtHandle.restore());
        }

		void Clear()
        {
        }

        template<int id, typename R, typename ... arglist>
        void stubMethod(R(C::*vMethod)(arglist...), MethodInvocationHandler<R, arglist...> *methodInvocationHandler) {
            auto offset = VTUtils::getOffset(vMethod);
            MethodProxyCreator<R, arglist...> creator;
            bind(creator.template createMethodProxy<id + 1>(offset), methodInvocationHandler);
        }

        void stubDtor(MethodInvocationHandler<void> *methodInvocationHandler) {
            auto offset = VTUtils::getDestructorOffset<C>();
            MethodProxyCreator<void> creator;
            bindDtor(creator.createMethodProxy<0>(offset), methodInvocationHandler);
        }

        template<typename R, typename ... arglist>
        bool isMethodStubbed(R(C::*vMethod)(arglist...)) {
            unsigned int offset = VTUtils::getOffset(vMethod);
            return isBinded(offset);
        }

        bool isDtorStubbed() {
            unsigned int offset = VTUtils::getDestructorOffset<C>();
            return isBinded(offset);
        }

        template<typename R, typename ... arglist>
        Destructible *getMethodMock(R(C::*vMethod)(arglist...)) {
            auto offset = VTUtils::getOffset(vMethod);
            std::shared_ptr<Destructible> ptr = _methodMocks[offset];
            return ptr.get();
        }

        Destructible *getDtorMock() {
            auto offset = VTUtils::getDestructorOffset<C>();
            std::shared_ptr<Destructible> ptr = _methodMocks[offset];
            return ptr.get();
        }

        template<typename DATA_TYPE, typename ... arglist>
        void stubDataMember(DATA_TYPE C::*member, const arglist &... initargs) {
            DATA_TYPE C::*theMember = (DATA_TYPE C::*) member;
            C &mock = get();
            DATA_TYPE *memberPtr = &(mock.*theMember);
            _members.push_back(
                    std::shared_ptr<DataMemeberWrapper < DATA_TYPE, arglist...> >
                    {new DataMemeberWrapper < DATA_TYPE, arglist...>(memberPtr,
                    initargs...)});
        }

        template<typename DATA_TYPE>
        void getMethodMocks(std::vector<DATA_TYPE> &into) const {
            for (std::shared_ptr<Destructible> ptr : _methodMocks) {
                DATA_TYPE p = dynamic_cast<DATA_TYPE>(ptr.get());
                if (p) {
                    into.push_back(p);
                }
            }
        }

        VirtualTable<C, baseclasses...> &getOriginalVT() {
            VirtualTable<C, baseclasses...> &vt = originalVtHandle.restore();
            return vt;
        }

    private:

        template<typename DATA_TYPE, typename ... arglist>
        class DataMemeberWrapper : public Destructible {
        private:
            DATA_TYPE *dataMember;
        public:
            DataMemeberWrapper(DATA_TYPE *dataMem, const arglist &... initargs) :
                    dataMember(dataMem) {
                new(dataMember) DATA_TYPE{initargs ...};
            }

            ~DataMemeberWrapper() override
            {
                dataMember->~DATA_TYPE();
            }
        };

        static_assert(sizeof(C) == sizeof(FakeObject<C, baseclasses...>), "This is a problem");

        C &instance;
        typename VirtualTable<C, baseclasses...>::Handle originalVtHandle;
        VirtualTable<C, baseclasses...> _cloneVt;

        std::vector<std::shared_ptr<Destructible>> _methodMocks;
        std::vector<std::shared_ptr<Destructible>> _members;
        std::vector<unsigned int> _offsets;
        InvocationHandlers _invocationHandlers;

        FakeObject<C, baseclasses...> &getFake() {
            return reinterpret_cast<FakeObject<C, baseclasses...> &>(instance);
        }

        void bind(const MethodProxy &methodProxy, Destructible *invocationHandler) {
            getFake().setMethod(methodProxy.getOffset(), methodProxy.getProxy());
            _methodMocks[methodProxy.getOffset()].reset(invocationHandler);
            _offsets[methodProxy.getOffset()] = methodProxy.getId();
        }

        void bindDtor(const MethodProxy &methodProxy, Destructible *invocationHandler) {
            getFake().setDtor(methodProxy.getProxy());
            _methodMocks[methodProxy.getOffset()].reset(invocationHandler);
            _offsets[methodProxy.getOffset()] = methodProxy.getId();
        }

        template<typename DATA_TYPE>
        DATA_TYPE getMethodMock(unsigned int offset) {
            std::shared_ptr<Destructible> ptr = _methodMocks[offset];
            return dynamic_cast<DATA_TYPE>(ptr.get());
        }

        template<typename BaseClass>
        void checkMultipleInheritance() {
            C *ptr = (C *) (unsigned int) 1;
            BaseClass *basePtr = ptr;
            int delta = (unsigned long) basePtr - (unsigned long) ptr;
            if (delta > 0) {


                throw std::invalid_argument(std::string("multiple inheritance is not supported"));
            }
        }

        bool isBinded(unsigned int offset) {
            std::shared_ptr<Destructible> ptr = _methodMocks[offset];
            return ptr.get() != nullptr;
        }

    };
}
#include <functional>
#include <type_traits>
#include <memory>
#include <iosfwd>
#include <vector>
#include <functional>
#include <tuple>
#include <tuple>

namespace fakeit {

    template<int N>
    struct apply_func {
        template<typename R, typename ... ArgsF, typename ... ArgsT, typename ... Args>
        static R applyTuple(std::function<R(ArgsF &...)> f, std::tuple<ArgsT...> &t, Args &... args) {
            return apply_func<N - 1>::template applyTuple(f, t, std::get<N - 1>(t), args...);
        }
    };

    template<>
    struct apply_func < 0 > {
        template<typename R, typename ... ArgsF, typename ... ArgsT, typename ... Args>
        static R applyTuple(std::function<R(ArgsF &...)> f, std::tuple<ArgsT...> & , Args &... args) {
            return f(args...);
        }
    };

    struct TupleDispatcher {

        template<typename R, typename ... ArgsF, typename ... ArgsT>
        static R applyTuple(std::function<R(ArgsF &...)> f, std::tuple<ArgsT...> &t) {
            return apply_func<sizeof...(ArgsT)>::template applyTuple(f, t);
        }

        template<typename R, typename ...arglist>
        static R invoke(std::function<R(arglist &...)> func, const std::tuple<arglist...> &arguments) {
            std::tuple<arglist...> &args = const_cast<std::tuple<arglist...> &>(arguments);
            return applyTuple(func, args);
        }

        template<typename TupleType, typename FunctionType>
        static void for_each(TupleType &&, FunctionType &,
            std::integral_constant<size_t, std::tuple_size<typename std::remove_reference<TupleType>::type>::value>) {
        }

        template<std::size_t I, typename TupleType, typename FunctionType, typename = typename std::enable_if<
            I != std::tuple_size<typename std::remove_reference<TupleType>::type>::value>::type>
            static void for_each(TupleType &&t, FunctionType &f, std::integral_constant<size_t, I>) {
            f(I, std::get < I >(t));
            for_each(std::forward < TupleType >(t), f, std::integral_constant<size_t, I + 1>());
        }

        template<typename TupleType, typename FunctionType>
        static void for_each(TupleType &&t, FunctionType &f) {
            for_each(std::forward < TupleType >(t), f, std::integral_constant<size_t, 0>());
        }

        template<typename TupleType1, typename TupleType2, typename FunctionType>
        static void for_each(TupleType1 &&, TupleType2 &&, FunctionType &,
            std::integral_constant<size_t, std::tuple_size<typename std::remove_reference<TupleType1>::type>::value>) {
        }

        template<std::size_t I, typename TupleType1, typename TupleType2, typename FunctionType, typename = typename std::enable_if<
            I != std::tuple_size<typename std::remove_reference<TupleType1>::type>::value>::type>
            static void for_each(TupleType1 &&t, TupleType2 &&t2, FunctionType &f, std::integral_constant<size_t, I>) {
            f(I, std::get < I >(t), std::get < I >(t2));
            for_each(std::forward < TupleType1 >(t), std::forward < TupleType2 >(t2), f, std::integral_constant<size_t, I + 1>());
        }

        template<typename TupleType1, typename TupleType2, typename FunctionType>
        static void for_each(TupleType1 &&t, TupleType2 &&t2, FunctionType &f) {
            for_each(std::forward < TupleType1 >(t), std::forward < TupleType2 >(t2), f, std::integral_constant<size_t, 0>());
        }
    };
}
namespace fakeit {

    template<typename R, typename ... arglist>
    struct ActualInvocationHandler : Destructible {
        virtual R handleMethodInvocation(ArgumentsTuple<arglist...> & args) = 0;
    };

}
#include <functional>
#include <tuple>
#include <string>
#include <iosfwd>
#include <type_traits>
#include <typeinfo>

namespace fakeit {

    struct DefaultValueInstatiationException {
        virtual ~DefaultValueInstatiationException() = default;

        virtual std::string what() const = 0;
    };


    template<class C>
    struct is_constructible_type {
        static const bool value =
                std::is_default_constructible<typename naked_type<C>::type>::value
                && !std::is_abstract<typename naked_type<C>::type>::value;
    };

    template<class C, class Enable = void>
    struct DefaultValue;

    template<class C>
    struct DefaultValue<C, typename std::enable_if<!is_constructible_type<C>::value>::type> {
        static C &value() {
            if (std::is_reference<C>::value) {
                typename naked_type<C>::type *ptr = nullptr;
                return *ptr;
            }

            class Exception : public DefaultValueInstatiationException {
                virtual std::string what() const

                override {
                    return (std::string("Type ") + std::string(typeid(C).name())
                            + std::string(
                            " is not default constructible. Could not instantiate a default return value")).c_str();
                }
            };

            throw Exception();
        }
    };

    template<class C>
    struct DefaultValue<C, typename std::enable_if<is_constructible_type<C>::value>::type> {
        static C &value() {
            static typename naked_type<C>::type val{};
            return val;
        }
    };


    template<>
    struct DefaultValue<void> {
        static void value() {
            return;
        }
    };

    template<>
    struct DefaultValue<bool> {
        static bool &value() {
            static bool value{false};
            return value;
        }
    };

    template<>
    struct DefaultValue<char> {
        static char &value() {
            static char value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<char16_t> {
        static char16_t &value() {
            static char16_t value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<char32_t> {
        static char32_t &value() {
            static char32_t value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<wchar_t> {
        static wchar_t &value() {
            static wchar_t value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<short> {
        static short &value() {
            static short value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<int> {
        static int &value() {
            static int value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<long> {
        static long &value() {
            static long value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<long long> {
        static long long &value() {
            static long long value{0};
            return value;
        }
    };

    template<>
    struct DefaultValue<std::string> {
        static std::string &value() {
            static std::string value{};
            return value;
        }
    };

}
namespace fakeit {

    struct IMatcher : Destructible {
        ~IMatcher() = default;
        virtual std::string format() const = 0;
    };

    template<typename T>
    struct TypedMatcher : IMatcher {
        virtual bool matches(const T &actual) const = 0;
    };

    template<typename T>
    struct TypedMatcherCreator {

        virtual ~TypedMatcherCreator() = default;

        virtual TypedMatcher<T> *createMatcher() const = 0;
    };

    template<typename T>
    struct ComparisonMatcherCreator : public TypedMatcherCreator<T> {

        virtual ~ComparisonMatcherCreator() = default;

        ComparisonMatcherCreator(const T &arg)
                : _expected(arg) {
        }

        struct Matcher : public TypedMatcher<T> {
            Matcher(const T &expected)
                    : _expected(expected) {
            }

            const T _expected;
        };

        const T &_expected;
    };

    namespace internal {
        template<typename T>
        struct TypedAnyMatcher : public TypedMatcherCreator<T> {

            virtual ~TypedAnyMatcher() = default;

            TypedAnyMatcher() {
            }

            struct Matcher : public TypedMatcher<T> {
                virtual bool matches(const T &) const override {
                    return true;
                }

                virtual std::string format() const override {
                    return "Any";
                }
            };

            virtual TypedMatcher<T> *createMatcher() const override {
                return new Matcher();
            }

        };

        template<typename T>
        struct EqMatcherCreator : public ComparisonMatcherCreator<T> {

            virtual ~EqMatcherCreator() = default;

            EqMatcherCreator(const T &expected)
                    : ComparisonMatcherCreator<T>(expected) {
            }

            struct Matcher : public ComparisonMatcherCreator<T>::Matcher {
                Matcher(const T &expected)
                        : ComparisonMatcherCreator<T>::Matcher(expected) {
                }

                virtual std::string format() const override {
                    return TypeFormatter<T>::format(this->_expected);
                }

                virtual bool matches(const T &actual) const override {
                    return actual == this->_expected;
                }
            };

            virtual TypedMatcher<T> *createMatcher() const {
                return new Matcher(this->_expected);
            }

        };

        template<typename T>
        struct GtMatcherCreator : public ComparisonMatcherCreator<T> {

            virtual ~GtMatcherCreator() = default;

            GtMatcherCreator(const T &expected)
                    : ComparisonMatcherCreator<T>(expected) {
            }

            struct Matcher : public ComparisonMatcherCreator<T>::Matcher {
                Matcher(const T &expected)
                        : ComparisonMatcherCreator<T>::Matcher(expected) {
                }

                virtual bool matches(const T &actual) const override {
                    return actual > this->_expected;
                }

                virtual std::string format() const override {
                    return std::string(">") + TypeFormatter<T>::format(this->_expected);
                }
            };

            virtual TypedMatcher<T> *createMatcher() const override {
                return new Matcher(this->_expected);
            }
        };

        template<typename T>
        struct GeMatcherCreator : public ComparisonMatcherCreator<T> {

            virtual ~GeMatcherCreator() = default;

            GeMatcherCreator(const T &expected)
                    : ComparisonMatcherCreator<T>(expected) {
            }

            struct Matcher : public ComparisonMatcherCreator<T>::Matcher {
                Matcher(const T &expected)
                        : ComparisonMatcherCreator<T>::Matcher(expected) {
                }

                virtual bool matches(const T &actual) const override {
                    return actual >= this->_expected;
                }

                virtual std::string format() const override {
                    return std::string(">=") + TypeFormatter<T>::format(this->_expected);
                }
            };

            virtual TypedMatcher<T> *createMatcher() const override {
                return new Matcher(this->_expected);
            }
        };

        template<typename T>
        struct LtMatcherCreator : public ComparisonMatcherCreator<T> {

            virtual ~LtMatcherCreator() = default;

            LtMatcherCreator(const T &expected)
                    : ComparisonMatcherCreator<T>(expected) {
            }

            struct Matcher : public ComparisonMatcherCreator<T>::Matcher {
                Matcher(const T &expected)
                        : ComparisonMatcherCreator<T>::Matcher(expected) {
                }

                virtual bool matches(const T &actual) const override {
                    return actual < this->_expected;
                }

                virtual std::string format() const override {
                    return std::string("<") + TypeFormatter<T>::format(this->_expected);
                }
            };

            virtual TypedMatcher<T> *createMatcher() const override {
                return new Matcher(this->_expected);
            }

        };

        template<typename T>
        struct LeMatcherCreator : public ComparisonMatcherCreator<T> {

            virtual ~LeMatcherCreator() = default;

            LeMatcherCreator(const T &expected)
                    : ComparisonMatcherCreator<T>(expected) {
            }

            struct Matcher : public ComparisonMatcherCreator<T>::Matcher {
                Matcher(const T &expected)
                        : ComparisonMatcherCreator<T>::Matcher(expected) {
                }

                virtual bool matches(const T &actual) const override {
                    return actual <= this->_expected;
                }

                virtual std::string format() const override {
                    return std::string("<=") + TypeFormatter<T>::format(this->_expected);
                }
            };

            virtual TypedMatcher<T> *createMatcher() const override {
                return new Matcher(this->_expected);
            }

        };

        template<typename T>
        struct NeMatcherCreator : public ComparisonMatcherCreator<T> {

            virtual ~NeMatcherCreator() = default;

            NeMatcherCreator(const T &expected)
                    : ComparisonMatcherCreator<T>(expected) {
            }

            struct Matcher : public ComparisonMatcherCreator<T>::Matcher {
                Matcher(const T &expected)
                        : ComparisonMatcherCreator<T>::Matcher(expected) {
                }

                virtual bool matches(const T &actual) const override {
                    return actual != this->_expected;
                }

                virtual std::string format() const override {
                    return std::string("!=") + TypeFormatter<T>::format(this->_expected);
                }

            };

            virtual TypedMatcher<T> *createMatcher() const override {
                return new Matcher(this->_expected);
            }

        };
    }

    struct AnyMatcher {
    } static _;

    template<typename T>
    internal::TypedAnyMatcher<T> Any() {
        internal::TypedAnyMatcher<T> rv;
        return rv;
    }

    template<typename T>
    internal::EqMatcherCreator<T> Eq(const T &arg) {
        internal::EqMatcherCreator<T> rv(arg);
        return rv;
    }

    template<typename T>
    internal::GtMatcherCreator<T> Gt(const T &arg) {
        internal::GtMatcherCreator<T> rv(arg);
        return rv;
    }

    template<typename T>
    internal::GeMatcherCreator<T> Ge(const T &arg) {
        internal::GeMatcherCreator<T> rv(arg);
        return rv;
    }

    template<typename T>
    internal::LtMatcherCreator<T> Lt(const T &arg) {
        internal::LtMatcherCreator<T> rv(arg);
        return rv;
    }

    template<typename T>
    internal::LeMatcherCreator<T> Le(const T &arg) {
        internal::LeMatcherCreator<T> rv(arg);
        return rv;
    }

    template<typename T>
    internal::NeMatcherCreator<T> Ne(const T &arg) {
        internal::NeMatcherCreator<T> rv(arg);
        return rv;
    }

}

namespace fakeit {

    template<typename ... arglist>
    struct ArgumentsMatcherInvocationMatcher : public ActualInvocation<arglist...>::Matcher {

        virtual ~ArgumentsMatcherInvocationMatcher() {
            for (unsigned int i = 0; i < _matchers.size(); i++)
                delete _matchers[i];
        }

        ArgumentsMatcherInvocationMatcher(const std::vector<Destructible *> &args)
                : _matchers(args) {
        }

        virtual bool matches(ActualInvocation<arglist...> &invocation) override {
            if (invocation.getActualMatcher() == this)
                return true;
            return matches(invocation.getActualArguments());
        }

        virtual std::string format() const override {
            std::ostringstream out;
            out << "(";
            for (unsigned int i = 0; i < _matchers.size(); i++) {
                if (i > 0) out << ", ";
                IMatcher *m = dynamic_cast<IMatcher *>(_matchers[i]);
                out << m->format();
            }
            out << ")";
            return out.str();
        }

    private:

        struct MatchingLambda {
            MatchingLambda(const std::vector<Destructible *> &matchers)
                    : _matchers(matchers) {
            }

            template<typename A>
            void operator()(int index, A &actualArg) {
                TypedMatcher<typename naked_type<A>::type> *matcher =
                        dynamic_cast<TypedMatcher<typename naked_type<A>::type> *>(_matchers[index]);
                if (_matching)
                    _matching = matcher->matches(actualArg);
            }

            bool isMatching() {
                return _matching;
            }

        private:
            bool _matching = true;
            const std::vector<Destructible *> &_matchers;
        };

        virtual bool matches(ArgumentsTuple<arglist...>& actualArguments) {
            MatchingLambda l(_matchers);
            fakeit::TupleDispatcher::for_each(actualArguments, l);
            return l.isMatching();
        }

        const std::vector<Destructible *> _matchers;
    };
































    template<typename ... arglist>
    struct UserDefinedInvocationMatcher : ActualInvocation<arglist...>::Matcher {
        virtual ~UserDefinedInvocationMatcher() = default;

        UserDefinedInvocationMatcher(std::function<bool(arglist &...)> match)
                : matcher{match} {
        }

        virtual bool matches(ActualInvocation<arglist...> &invocation) override {
            if (invocation.getActualMatcher() == this)
                return true;
            return matches(invocation.getActualArguments());
        }

        virtual std::string format() const override {
            return {"( user defined matcher )"};
        }

    private:
        virtual bool matches(ArgumentsTuple<arglist...>& actualArguments) {
            return TupleDispatcher::invoke<bool, typename tuple_arg<arglist>::type...>(matcher, actualArguments);
        }

        const std::function<bool(arglist &...)> matcher;
    };

    template<typename ... arglist>
    struct DefaultInvocationMatcher : public ActualInvocation<arglist...>::Matcher {

        virtual ~DefaultInvocationMatcher() = default;

        DefaultInvocationMatcher() {
        }

        virtual bool matches(ActualInvocation<arglist...> &invocation) override {
            return matches(invocation.getActualArguments());
        }

        virtual std::string format() const override {
            return {"( Any arguments )"};
        }

    private:

        virtual bool matches(const ArgumentsTuple<arglist...>&) {
            return true;
        }
    };

}

namespace fakeit {


    template<typename R, typename ... arglist>
    class RecordedMethodBody : public MethodInvocationHandler<R, arglist...>, public ActualInvocationsSource, public ActualInvocationsContainer {

        struct MatchedInvocationHandler : ActualInvocationHandler<R, arglist...> {

            virtual ~MatchedInvocationHandler() = default;

            MatchedInvocationHandler(typename ActualInvocation<arglist...>::Matcher *matcher,
                ActualInvocationHandler<R, arglist...> *invocationHandler) :
                    _matcher{matcher}, _invocationHandler{invocationHandler} {
            }

            virtual R handleMethodInvocation(ArgumentsTuple<arglist...> & args) override
            {
                Destructible &destructable = *_invocationHandler;
                ActualInvocationHandler<R, arglist...> &invocationHandler = dynamic_cast<ActualInvocationHandler<R, arglist...> &>(destructable);
                return invocationHandler.handleMethodInvocation(args);
            }

            typename ActualInvocation<arglist...>::Matcher &getMatcher() const {
                Destructible &destructable = *_matcher;
                typename ActualInvocation<arglist...>::Matcher &matcher = dynamic_cast<typename ActualInvocation<arglist...>::Matcher &>(destructable);
                return matcher;
            }

        private:
            std::shared_ptr<Destructible> _matcher;
            std::shared_ptr<Destructible> _invocationHandler;
        };


        FakeitContext &_fakeit;
        MethodInfo _method;

        std::vector<std::shared_ptr<Destructible>> _invocationHandlers;
        std::vector<std::shared_ptr<Destructible>> _actualInvocations;

        MatchedInvocationHandler *buildMatchedInvocationHandler(
                typename ActualInvocation<arglist...>::Matcher *invocationMatcher,
                ActualInvocationHandler<R, arglist...> *invocationHandler) {
            return new MatchedInvocationHandler(invocationMatcher, invocationHandler);
        }

        MatchedInvocationHandler *getInvocationHandlerForActualArgs(ActualInvocation<arglist...> &invocation) {
            for (auto i = _invocationHandlers.rbegin(); i != _invocationHandlers.rend(); ++i) {
                std::shared_ptr<Destructible> curr = *i;
                Destructible &destructable = *curr;
                MatchedInvocationHandler &im = asMatchedInvocationHandler(destructable);
                if (im.getMatcher().matches(invocation)) {
                    return &im;
                }
            }
            return nullptr;
        }

        MatchedInvocationHandler &asMatchedInvocationHandler(Destructible &destructable) {
            MatchedInvocationHandler &im = dynamic_cast<MatchedInvocationHandler &>(destructable);
            return im;
        }

        ActualInvocation<arglist...> &asActualInvocation(Destructible &destructable) const {
            ActualInvocation<arglist...> &invocation = dynamic_cast<ActualInvocation<arglist...> &>(destructable);
            return invocation;
        }

    public:

        RecordedMethodBody(FakeitContext &fakeit, std::string name) :
                _fakeit(fakeit), _method{MethodInfo::nextMethodOrdinal(), name} { }

        virtual ~RecordedMethodBody() NO_THROWS {
        }

        MethodInfo &getMethod() {
            return _method;
        }

        bool isOfMethod(MethodInfo &method) {

            return method.id() == _method.id();
        }

        void addMethodInvocationHandler(typename ActualInvocation<arglist...>::Matcher *matcher,
            ActualInvocationHandler<R, arglist...> *invocationHandler) {
            ActualInvocationHandler<R, arglist...> *mock = buildMatchedInvocationHandler(matcher, invocationHandler);
            std::shared_ptr<Destructible> destructable{mock};
            _invocationHandlers.push_back(destructable);
        }

        void reset() {
            _invocationHandlers.clear();
            _actualInvocations.clear();
        }

		void clear() override {
			_actualInvocations.clear();
		}

        R handleMethodInvocation(const typename fakeit::production_arg<arglist>::type... args) override {
            unsigned int ordinal = Invocation::nextInvocationOrdinal();
            MethodInfo &method = this->getMethod();
            auto actualInvocation = new ActualInvocation<arglist...>(ordinal, method, std::forward<const typename fakeit::production_arg<arglist>::type>(args)...);


            std::shared_ptr<Destructible> actualInvocationDtor{actualInvocation};

            auto invocationHandler = getInvocationHandlerForActualArgs(*actualInvocation);
            if (invocationHandler) {
                auto &matcher = invocationHandler->getMatcher();
                actualInvocation->setActualMatcher(&matcher);
                _actualInvocations.push_back(actualInvocationDtor);
                try {
                    return invocationHandler->handleMethodInvocation(actualInvocation->getActualArguments());
                } catch (NoMoreRecordedActionException &) {
                }
            }

            UnexpectedMethodCallEvent event(UnexpectedType::Unmatched, *actualInvocation);
            _fakeit.handle(event);
            std::string format{_fakeit.format(event)};
            UnexpectedMethodCallException e(format);
            throw e;
        }

        void scanActualInvocations(const std::function<void(ActualInvocation<arglist...> &)> &scanner) {
            for (auto destructablePtr : _actualInvocations) {
                ActualInvocation<arglist...> &invocation = asActualInvocation(*destructablePtr);
                scanner(invocation);
            }
        }

        void getActualInvocations(std::unordered_set<Invocation *> &into) const override {
            for (auto destructablePtr : _actualInvocations) {
                Invocation &invocation = asActualInvocation(*destructablePtr);
                into.insert(&invocation);
            }
        }

        void setMethodDetails(const std::string &mockName, const std::string &methodName) {
            const std::string fullName{mockName + "." + methodName};
            _method.setName(fullName);
        }

    };

}
#include <functional>
#include <type_traits>
#include <stdexcept>
#include <utility>
#include <functional>
#include <type_traits>

namespace fakeit {

    struct Quantity {
        Quantity(const int q) :
                quantity(q) {
        }

        const int quantity;
    } static Once(1);

    template<typename R>
    struct Quantifier : public Quantity {
        Quantifier(const int q, const R &val) :
                Quantity(q), value(val) {
        }

        const R &value;
    };

    template<>
    struct Quantifier<void> : public Quantity {
        explicit Quantifier(const int q) :
                Quantity(q) {
        }
    };

    struct QuantifierFunctor : public Quantifier<void> {
        QuantifierFunctor(const int q) :
                Quantifier<void>(q) {
        }

        template<typename R>
        Quantifier<R> operator()(const R &value) {
            return Quantifier<R>(quantity, value);
        }
    };

    template<int q>
    struct Times : public Quantity {

        Times<q>() : Quantity(q) { }

        template<typename R>
        static Quantifier<R> of(const R &value) {
            return Quantifier<R>(q, value);
        }

        static Quantifier<void> Void() {
            return Quantifier<void>(q);
        }
    };

#if defined (__GNUG__) || (_MSC_VER >= 1900)

    inline QuantifierFunctor operator
    ""

    _Times(unsigned long long n) {
        return QuantifierFunctor((int) n);
    }

    inline QuantifierFunctor operator
    ""

    _Time(unsigned long long n) {
        if (n != 1)
            throw std::invalid_argument("Only 1_Time is supported. Use X_Times (with s) if X is bigger than 1");
        return QuantifierFunctor((int) n);
    }

#endif

}
#include <functional>
#include <atomic>
#include <tuple>
#include <type_traits>


namespace fakeit {

    template<typename R, typename ... arglist>
    struct Action : Destructible {
        virtual R invoke(const ArgumentsTuple<arglist...> &) = 0;

        virtual bool isDone() = 0;
    };

    template<typename R, typename ... arglist>
    struct Repeat : Action<R, arglist...> {
        virtual ~Repeat() = default;

        Repeat(std::function<R(typename fakeit::test_arg<arglist>::type...)> func) :
                f(func), times(1) {
        }

        Repeat(std::function<R(typename fakeit::test_arg<arglist>::type...)> func, long t) :
                f(func), times(t) {
        }

        virtual R invoke(const ArgumentsTuple<arglist...> & args) override {
            times--;
            return TupleDispatcher::invoke<R, arglist...>(f, args);
        }

        virtual bool isDone() override {
            return times == 0;
        }

    private:
        std::function<R(typename fakeit::test_arg<arglist>::type...)> f;
        long times;
    };

    template<typename R, typename ... arglist>
    struct RepeatForever : public Action<R, arglist...> {

        virtual ~RepeatForever() = default;

        RepeatForever(std::function<R(typename fakeit::test_arg<arglist>::type...)> func) :
                f(func) {
        }

        virtual R invoke(const ArgumentsTuple<arglist...> & args) override {
            return TupleDispatcher::invoke<R, arglist...>(f, args);
        }

        virtual bool isDone() override {
            return false;
        }

    private:
        std::function<R(typename fakeit::test_arg<arglist>::type...)> f;
    };

    template<typename R, typename ... arglist>
    struct ReturnDefaultValue : public Action<R, arglist...> {
        virtual ~ReturnDefaultValue() = default;

        virtual R invoke(const ArgumentsTuple<arglist...> &) override {
            return DefaultValue<R>::value();
        }

        virtual bool isDone() override {
            return false;
        }
    };

    template<typename R, typename ... arglist>
    struct ReturnDelegateValue : public Action<R, arglist...> {

        ReturnDelegateValue(std::function<R(const typename fakeit::test_arg<arglist>::type...)> delegate) : _delegate(delegate) { }

        virtual ~ReturnDelegateValue() = default;

        virtual R invoke(const ArgumentsTuple<arglist...> & args) override {
            return TupleDispatcher::invoke<R, arglist...>(_delegate, args);
        }

        virtual bool isDone() override {
            return false;
        }

    private:
        std::function<R(const typename fakeit::test_arg<arglist>::type...)> _delegate;
    };

}

namespace fakeit {

    template<typename R, typename ... arglist>
    struct MethodStubbingProgress {

        virtual ~MethodStubbingProgress() THROWS {
        }

        template<typename U = R>
        typename std::enable_if<!std::is_reference<U>::value, MethodStubbingProgress<R, arglist...> &>::type
        Return(const R &r) {
            return Do([r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
        }

        template<typename U = R>
        typename std::enable_if<std::is_reference<U>::value, MethodStubbingProgress<R, arglist...> &>::type
        Return(const R &r) {
            return Do([&r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
        }

        MethodStubbingProgress<R, arglist...> &
        Return(const Quantifier<R> &q) {
            const R &value = q.value;
            auto method = [value](const arglist &...) -> R { return value; };
            return DoImpl(new Repeat<R, arglist...>(method, q.quantity));
        }

        template<typename first, typename second, typename ... tail>
        MethodStubbingProgress<R, arglist...> &
        Return(const first &f, const second &s, const tail &... t) {
            Return(f);
            return Return(s, t...);
        }


        template<typename U = R>
        typename std::enable_if<!std::is_reference<U>::value, void>::type
        AlwaysReturn(const R &r) {
            return AlwaysDo([r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
        }

        template<typename U = R>
        typename std::enable_if<std::is_reference<U>::value, void>::type
        AlwaysReturn(const R &r) {
            return AlwaysDo([&r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; });
        }

        MethodStubbingProgress<R, arglist...> &
        Return() {
            return Do([](const typename fakeit::test_arg<arglist>::type...) -> R { return DefaultValue<R>::value(); });
        }

        void AlwaysReturn() {
            return AlwaysDo([](const typename fakeit::test_arg<arglist>::type...) -> R { return DefaultValue<R>::value(); });
        }

        template<typename E>
        MethodStubbingProgress<R, arglist...> &Throw(const E &e) {
            return Do([e](const typename fakeit::test_arg<arglist>::type...) -> R { throw e; });
        }

        template<typename E>
        MethodStubbingProgress<R, arglist...> &
        Throw(const Quantifier<E> &q) {
            const E &value = q.value;
            auto method = [value](const arglist &...) -> R { throw value; };
            return DoImpl(new Repeat<R, arglist...>(method, q.quantity));
        }

        template<typename first, typename second, typename ... tail>
        MethodStubbingProgress<R, arglist...> &
        Throw(const first &f, const second &s, const tail &... t) {
            Throw(f);
            return Throw(s, t...);
        }

        template<typename E>
        void AlwaysThrow(const E &e) {
            return AlwaysDo([e](const typename fakeit::test_arg<arglist>::type...) -> R { throw e; });
        }

        virtual MethodStubbingProgress<R, arglist...> &
            Do(std::function<R(const typename fakeit::test_arg<arglist>::type...)> method) {
            return DoImpl(new Repeat<R, arglist...>(method));
        }

        template<typename F>
        MethodStubbingProgress<R, arglist...> &
        Do(const Quantifier<F> &q) {
            return DoImpl(new Repeat<R, arglist...>(q.value, q.quantity));
        }

        template<typename first, typename second, typename ... tail>
        MethodStubbingProgress<R, arglist...> &
        Do(const first &f, const second &s, const tail &... t) {
            Do(f);
            return Do(s, t...);
        }

        virtual void AlwaysDo(std::function<R(const typename fakeit::test_arg<arglist>::type...)> method) {
            DoImpl(new RepeatForever<R, arglist...>(method));
        }

    protected:

        virtual MethodStubbingProgress<R, arglist...> &DoImpl(Action<R, arglist...> *action) = 0;

    private:
        MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete;
    };


    template<typename ... arglist>
    struct MethodStubbingProgress<void, arglist...> {

        virtual ~MethodStubbingProgress() THROWS {
        }

        MethodStubbingProgress<void, arglist...> &Return() {
            auto lambda = [](const typename fakeit::test_arg<arglist>::type...) -> void {
                return DefaultValue<void>::value();
            };
            return Do(lambda);
        }

        virtual MethodStubbingProgress<void, arglist...> &Do(
            std::function<void(const typename fakeit::test_arg<arglist>::type...)> method) {
            return DoImpl(new Repeat<void, arglist...>(method));
        }


        void AlwaysReturn() {
            return AlwaysDo([](const typename fakeit::test_arg<arglist>::type...) -> void { return DefaultValue<void>::value(); });
        }

        MethodStubbingProgress<void, arglist...> &
        Return(const Quantifier<void> &q) {
            auto method = [](const arglist &...) -> void { return DefaultValue<void>::value(); };
            return DoImpl(new Repeat<void, arglist...>(method, q.quantity));
        }

        template<typename E>
        MethodStubbingProgress<void, arglist...> &Throw(const E &e) {
            return Do([e](const typename fakeit::test_arg<arglist>::type...) -> void { throw e; });
        }

        template<typename E>
        MethodStubbingProgress<void, arglist...> &
        Throw(const Quantifier<E> &q) {
            const E &value = q.value;
            auto method = [value](const typename fakeit::test_arg<arglist>::type...) -> void { throw value; };
            return DoImpl(new Repeat<void, arglist...>(method, q.quantity));
        }

        template<typename first, typename second, typename ... tail>
        MethodStubbingProgress<void, arglist...> &
        Throw(const first &f, const second &s, const tail &... t) {
            Throw(f);
            return Throw(s, t...);
        }

        template<typename E>
        void AlwaysThrow(const E e) {
            return AlwaysDo([e](const typename fakeit::test_arg<arglist>::type...) -> void { throw e; });
        }

           template<typename F>
        MethodStubbingProgress<void, arglist...> &
        Do(const Quantifier<F> &q) {
            return DoImpl(new Repeat<void, arglist...>(q.value, q.quantity));
        }

        template<typename first, typename second, typename ... tail>
        MethodStubbingProgress<void, arglist...> &
        Do(const first &f, const second &s, const tail &... t) {
            Do(f);
            return Do(s, t...);
        }

        virtual void AlwaysDo(std::function<void(const typename fakeit::test_arg<arglist>::type...)> method) {
            DoImpl(new RepeatForever<void, arglist...>(method));
        }

    protected:

        virtual MethodStubbingProgress<void, arglist...> &DoImpl(Action<void, arglist...> *action) = 0;

    private:
        MethodStubbingProgress &operator=(const MethodStubbingProgress &other) = delete;
    };


}
#include <vector>
#include <functional>

namespace fakeit {

    class Finally {
    private:
        std::function<void()> _finallyClause;

        Finally(const Finally &);

        Finally &operator=(const Finally &);

    public:
        explicit Finally(std::function<void()> f) :
                _finallyClause(f) {
        }

        ~Finally() {
            _finallyClause();
        }
    };
}

namespace fakeit {


    template<typename R, typename ... arglist>
    struct ActionSequence : ActualInvocationHandler<R,arglist...> {

        ActionSequence() {
            clear();
        }

        void AppendDo(Action<R, arglist...> *action) {
            append(action);
        }

        virtual R handleMethodInvocation(ArgumentsTuple<arglist...> & args) override
        {
            std::shared_ptr<Destructible> destructablePtr = _recordedActions.front();
            Destructible &destructable = *destructablePtr;
            Action<R, arglist...> &action = dynamic_cast<Action<R, arglist...> &>(destructable);
            std::function<void()> finallyClause = [&]() -> void {
                if (action.isDone())
                    _recordedActions.erase(_recordedActions.begin());
            };
            Finally onExit(finallyClause);
            return action.invoke(args);
        }

    private:

        struct NoMoreRecordedAction : Action<R, arglist...> {







            virtual R invoke(const ArgumentsTuple<arglist...> &) override {
                throw NoMoreRecordedActionException();
            }

            virtual bool isDone() override {
                return false;
            }
        };

        void append(Action<R, arglist...> *action) {
            std::shared_ptr<Destructible> destructable{action};
            _recordedActions.insert(_recordedActions.end() - 1, destructable);
        }

        void clear() {
            _recordedActions.clear();
            auto actionPtr = std::shared_ptr<Destructible> {new NoMoreRecordedAction()};
            _recordedActions.push_back(actionPtr);
        }

        std::vector<std::shared_ptr<Destructible>> _recordedActions;
    };

}

namespace fakeit {

    template<typename C, typename DATA_TYPE>
    class DataMemberStubbingRoot {
    private:

    public:
        DataMemberStubbingRoot(const DataMemberStubbingRoot &) = default;

        DataMemberStubbingRoot() = default;

        void operator=(const DATA_TYPE&) {
        }
    };

}
#include <functional>
#include <utility>
#include <type_traits>
#include <tuple>
#include <memory>
#include <vector>
#include <unordered_set>
#include <set>
#include <iosfwd>

namespace fakeit {

    struct Xaction {
        virtual void commit() = 0;
    };
}

namespace fakeit {


    template<typename R, typename ... arglist>
    struct SpyingContext : Xaction {
        virtual void appendAction(Action<R, arglist...> *action) = 0;

        virtual std::function<R(arglist&...)> getOriginalMethod() = 0;
    };
}
namespace fakeit {


    template<typename R, typename ... arglist>
    struct StubbingContext : public Xaction {
        virtual void appendAction(Action<R, arglist...> *action) = 0;
    };
}
#include <functional>
#include <type_traits>
#include <tuple>
#include <memory>
#include <vector>
#include <unordered_set>


namespace fakeit {

    template<unsigned int index, typename ... arglist>
    class MatchersCollector {

        std::vector<Destructible *> &_matchers;

    public:


        template<std::size_t N>
        using ArgType = typename std::tuple_element<N, std::tuple<arglist...>>::type;

        template<std::size_t N>
        using NakedArgType = typename naked_type<ArgType<index>>::type;

        template<std::size_t N>
        using ArgMatcherCreatorType = decltype(std::declval<TypedMatcherCreator<NakedArgType<N>>>());

        MatchersCollector(std::vector<Destructible *> &matchers)
                : _matchers(matchers) {
        }

        void CollectMatchers() {
        }

        template<typename Head>
        typename std::enable_if<
                std::is_constructible<NakedArgType<index>, Head>::value, void>
        ::type CollectMatchers(const Head &value) {

            TypedMatcher<NakedArgType<index>> *d = Eq<NakedArgType<index>>(value).createMatcher();
            _matchers.push_back(d);
        }

        template<typename Head, typename ...Tail>
        typename std::enable_if<
                std::is_constructible<NakedArgType<index>, Head>::value
                , void>
        ::type CollectMatchers(const Head &head, const Tail &... tail) {
            CollectMatchers(head);
            MatchersCollector<index + 1, arglist...> c(_matchers);
            c.CollectMatchers(tail...);
        }

        template<typename Head>
        typename std::enable_if<
                std::is_base_of<TypedMatcherCreator<NakedArgType<index>>, Head>::value, void>
        ::type CollectMatchers(const Head &creator) {
            TypedMatcher<NakedArgType<index>> *d = creator.createMatcher();
            _matchers.push_back(d);
        }

        template<typename Head, typename ...Tail>

        typename std::enable_if<
                std::is_base_of<TypedMatcherCreator<NakedArgType<index>>, Head>::value, void>
        ::type CollectMatchers(const Head &head, const Tail &... tail) {
            CollectMatchers(head);
            MatchersCollector<index + 1, arglist...> c(_matchers);
            c.CollectMatchers(tail...);
        }

        template<typename Head>
        typename std::enable_if<
                std::is_same<AnyMatcher, Head>::value, void>
        ::type CollectMatchers(const Head &) {
            TypedMatcher<NakedArgType<index>> *d = Any<NakedArgType<index>>().createMatcher();
            _matchers.push_back(d);
        }

        template<typename Head, typename ...Tail>
        typename std::enable_if<
                std::is_same<AnyMatcher, Head>::value, void>
        ::type CollectMatchers(const Head &head, const Tail &... tail) {
            CollectMatchers(head);
            MatchersCollector<index + 1, arglist...> c(_matchers);
            c.CollectMatchers(tail...);
        }

    };

}

namespace fakeit {

    template<typename R, typename ... arglist>
    class MethodMockingContext :
            public Sequence,
            public ActualInvocationsSource,
            public virtual StubbingContext<R, arglist...>,
            public virtual SpyingContext<R, arglist...>,
            private Invocation::Matcher {
    public:

        struct Context : Destructible {


            virtual typename std::function<R(arglist&...)> getOriginalMethod() = 0;

            virtual std::string getMethodName() = 0;

            virtual void addMethodInvocationHandler(typename ActualInvocation<arglist...>::Matcher *matcher,
                ActualInvocationHandler<R, arglist...> *invocationHandler) = 0;

            virtual void scanActualInvocations(const std::function<void(ActualInvocation<arglist...> &)> &scanner) = 0;

            virtual void setMethodDetails(std::string mockName, std::string methodName) = 0;

            virtual bool isOfMethod(MethodInfo &method) = 0;

            virtual ActualInvocationsSource &getInvolvedMock() = 0;
        };

    private:
        class Implementation {

            Context *_stubbingContext;
            ActionSequence<R, arglist...> *_recordedActionSequence;
            typename ActualInvocation<arglist...>::Matcher *_invocationMatcher;
            bool _commited;

            Context &getStubbingContext() const {
                return *_stubbingContext;
            }

        public:

            Implementation(Context *stubbingContext)
                    : _stubbingContext(stubbingContext),
                      _recordedActionSequence(new ActionSequence<R, arglist...>()),
                      _invocationMatcher
                              {
                                      new DefaultInvocationMatcher<arglist...>()}, _commited(false) {
            }

            ~Implementation() {
                delete _stubbingContext;
                if (!_commited) {

                    delete _recordedActionSequence;
                    delete _invocationMatcher;
                }
            }

            ActionSequence<R, arglist...> &getRecordedActionSequence() {
                return *_recordedActionSequence;
            }

            std::string format() const {
                std::string s = getStubbingContext().getMethodName();
                s += _invocationMatcher->format();
                return s;
            }

            void getActualInvocations(std::unordered_set<Invocation *> &into) const {
                auto scanner = [&](ActualInvocation<arglist...> &a) {
                    if (_invocationMatcher->matches(a)) {
                        into.insert(&a);
                    }
                };
                getStubbingContext().scanActualInvocations(scanner);
            }


            bool matches(Invocation &invocation) {
                MethodInfo &actualMethod = invocation.getMethod();
                if (!getStubbingContext().isOfMethod(actualMethod)) {
                    return false;
                }

                ActualInvocation<arglist...> &actualInvocation = dynamic_cast<ActualInvocation<arglist...> &>(invocation);
                return _invocationMatcher->matches(actualInvocation);
            }

            void commit() {
                getStubbingContext().addMethodInvocationHandler(_invocationMatcher, _recordedActionSequence);
                _commited = true;
            }

            void appendAction(Action<R, arglist...> *action) {
                getRecordedActionSequence().AppendDo(action);
            }

            void setMethodBodyByAssignment(std::function<R(const typename fakeit::test_arg<arglist>::type...)> method) {
                appendAction(new RepeatForever<R, arglist...>(method));
                commit();
            }

            void setMethodDetails(std::string mockName, std::string methodName) {
                getStubbingContext().setMethodDetails(mockName, methodName);
            }

            void getInvolvedMocks(std::vector<ActualInvocationsSource *> &into) const {
                into.push_back(&getStubbingContext().getInvolvedMock());
            }

            typename std::function<R(arglist &...)> getOriginalMethod() {
                return getStubbingContext().getOriginalMethod();
            }

            void setInvocationMatcher(typename ActualInvocation<arglist...>::Matcher *matcher) {
                delete _invocationMatcher;
                _invocationMatcher = matcher;
            }
        };

    protected:

        MethodMockingContext(Context *stubbingContext)
                : _impl{new Implementation(stubbingContext)} {
        }

        MethodMockingContext(MethodMockingContext &) = default;



        MethodMockingContext(MethodMockingContext &&other)
                : _impl(std::move(other._impl)) {
        }

        virtual ~MethodMockingContext() NO_THROWS { }

        std::string format() const override {
            return _impl->format();
        }

        unsigned int size() const override {
            return 1;
        }


        void getInvolvedMocks(std::vector<ActualInvocationsSource *> &into) const override {
            _impl->getInvolvedMocks(into);
        }

        void getExpectedSequence(std::vector<Invocation::Matcher *> &into) const override {
            const Invocation::Matcher *b = this;
            Invocation::Matcher *c = const_cast<Invocation::Matcher *>(b);
            into.push_back(c);
        }


        void getActualInvocations(std::unordered_set<Invocation *> &into) const override {
            _impl->getActualInvocations(into);
        }


        bool matches(Invocation &invocation) override {
            return _impl->matches(invocation);
        }

        void commit() override {
            _impl->commit();
        }

        void setMethodDetails(std::string mockName, std::string methodName) {
            _impl->setMethodDetails(mockName, methodName);
        }

        void setMatchingCriteria(std::function<bool(arglist &...)> predicate) {
            typename ActualInvocation<arglist...>::Matcher *matcher{
                    new UserDefinedInvocationMatcher<arglist...>(predicate)};
            _impl->setInvocationMatcher(matcher);
        }

        void setMatchingCriteria(const std::vector<Destructible *> &matchers) {
            typename ActualInvocation<arglist...>::Matcher *matcher{
                    new ArgumentsMatcherInvocationMatcher<arglist...>(matchers)};
            _impl->setInvocationMatcher(matcher);
        }


        void appendAction(Action<R, arglist...> *action) override {
            _impl->appendAction(action);
        }

        void setMethodBodyByAssignment(std::function<R(const typename fakeit::test_arg<arglist>::type...)> method) {
            _impl->setMethodBodyByAssignment(method);
        }

        template<class ...matcherCreators, class = typename std::enable_if<
                sizeof...(matcherCreators) == sizeof...(arglist)>::type>
        void setMatchingCriteria(const matcherCreators &... matcherCreator) {
            std::vector<Destructible *> matchers;

            MatchersCollector<0, arglist...> c(matchers);
            c.CollectMatchers(matcherCreator...);

            MethodMockingContext<R, arglist...>::setMatchingCriteria(matchers);
        }

    private:

        typename std::function<R(arglist&...)> getOriginalMethod() override {
            return _impl->getOriginalMethod();
        }

        std::shared_ptr<Implementation> _impl;
    };

    template<typename R, typename ... arglist>
    class MockingContext :
            public MethodMockingContext<R, arglist...> {
        MockingContext &operator=(const MockingContext &) = delete;

    public:

        MockingContext(typename MethodMockingContext<R, arglist...>::Context *stubbingContext)
                : MethodMockingContext<R, arglist...>(stubbingContext) {
        }

        MockingContext(MockingContext &) = default;

        MockingContext(MockingContext &&other)
                : MethodMockingContext<R, arglist...>(std::move(other)) {
        }

        MockingContext<R, arglist...> &setMethodDetails(std::string mockName, std::string methodName) {
            MethodMockingContext<R, arglist...>::setMethodDetails(mockName, methodName);
            return *this;
        }

        MockingContext<R, arglist...> &Using(const arglist &... args) {
            MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
            return *this;
        }

        template<class ...arg_matcher>
        MockingContext<R, arglist...> &Using(const arg_matcher &... arg_matchers) {
            MethodMockingContext<R, arglist...>::setMatchingCriteria(arg_matchers...);
            return *this;
        }

        MockingContext<R, arglist...> &Matching(std::function<bool(arglist &...)> matcher) {
            MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
            return *this;
        }

        MockingContext<R, arglist...> &operator()(const arglist &... args) {
            MethodMockingContext<R, arglist...>::setMatchingCriteria(args...);
            return *this;
        }

        MockingContext<R, arglist...> &operator()(std::function<bool(arglist &...)> matcher) {
            MethodMockingContext<R, arglist...>::setMatchingCriteria(matcher);
            return *this;
        }

        void operator=(std::function<R(arglist &...)> method) {
            MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
        }

        template<typename U = R>
        typename std::enable_if<!std::is_reference<U>::value, void>::type operator=(const R &r) {
            auto method = [r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; };
            MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
        }

        template<typename U = R>
        typename std::enable_if<std::is_reference<U>::value, void>::type operator=(const R &r) {
            auto method = [&r](const typename fakeit::test_arg<arglist>::type...) -> R { return r; };
            MethodMockingContext<R, arglist...>::setMethodBodyByAssignment(method);
        }
    };

    template<typename ... arglist>
    class MockingContext<void, arglist...> :
            public MethodMockingContext<void, arglist...> {
        MockingContext &operator=(const MockingContext &) = delete;

    public:

        MockingContext(typename MethodMockingContext<void, arglist...>::Context *stubbingContext)
                : MethodMockingContext<void, arglist...>(stubbingContext) {
        }

        MockingContext(MockingContext &) = default;

        MockingContext(MockingContext &&other)
                : MethodMockingContext<void, arglist...>(std::move(other)) {
        }

        MockingContext<void, arglist...> &setMethodDetails(std::string mockName, std::string methodName) {
            MethodMockingContext<void, arglist...>::setMethodDetails(mockName, methodName);
            return *this;
        }

        MockingContext<void, arglist...> &Using(const arglist &... args) {
            MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
            return *this;
        }

        template<class ...arg_matcher>
        MockingContext<void, arglist...> &Using(const arg_matcher &... arg_matchers) {
            MethodMockingContext<void, arglist...>::setMatchingCriteria(arg_matchers...);
            return *this;
        }

        MockingContext<void, arglist...> &Matching(std::function<bool(arglist &...)> matcher) {
            MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
            return *this;
        }

        MockingContext<void, arglist...> &operator()(const arglist &... args) {
            MethodMockingContext<void, arglist...>::setMatchingCriteria(args...);
            return *this;
        }

        MockingContext<void, arglist...> &operator()(std::function<bool(arglist &...)> matcher) {
            MethodMockingContext<void, arglist...>::setMatchingCriteria(matcher);
            return *this;
        }

        void operator=(std::function<void(arglist &...)> method) {
            MethodMockingContext<void, arglist...>::setMethodBodyByAssignment(method);
        }

    };

    class DtorMockingContext : public MethodMockingContext<void> {
    public:

        DtorMockingContext(MethodMockingContext<void>::Context *stubbingContext)
                : MethodMockingContext<void>(stubbingContext) {
        }

        DtorMockingContext(DtorMockingContext &other) : MethodMockingContext<void>(other) {
        }

        DtorMockingContext(DtorMockingContext &&other) : MethodMockingContext<void>(std::move(other)) {
        }

        void operator=(std::function<void()> method) {
            MethodMockingContext<void>::setMethodBodyByAssignment(method);
        }

        DtorMockingContext &setMethodDetails(std::string mockName, std::string methodName) {
            MethodMockingContext<void>::setMethodDetails(mockName, methodName);
            return *this;
        }
    };

}

namespace fakeit {


    template<typename C, typename ... baseclasses>
    class MockImpl : private MockObject<C>, public virtual ActualInvocationsSource {
    public:

        MockImpl(FakeitContext &fakeit, C &obj)
                : MockImpl<C, baseclasses...>(fakeit, obj, true) {
        }

        MockImpl(FakeitContext &fakeit)
                : MockImpl<C, baseclasses...>(fakeit, *(createFakeInstance()), false){
            FakeObject<C, baseclasses...> *fake = asFakeObject(_instanceOwner.get());
            fake->getVirtualTable().setCookie(1, this);
        }

        virtual ~MockImpl() NO_THROWS {
            _proxy.detach();
        }


        void getActualInvocations(std::unordered_set<Invocation *> &into) const override {
            std::vector<ActualInvocationsSource *> vec;
            _proxy.getMethodMocks(vec);
            for (ActualInvocationsSource *s : vec) {
                s->getActualInvocations(into);
            }
        }

	    void initDataMembersIfOwner()
	    {
		    if (isOwner()) {
			    FakeObject<C, baseclasses...> *fake = asFakeObject(_instanceOwner.get());
			    fake->initializeDataMembersArea();
		    }
	    }

	    void reset() {
            _proxy.Reset();
		    initDataMembersIfOwner();
	    }

		void clear()
        {
			std::vector<ActualInvocationsContainer *> vec;
			_proxy.getMethodMocks(vec);
			for (ActualInvocationsContainer *s : vec) {
				s->clear();
			}
			initDataMembersIfOwner();
        }

        virtual C &get() override {
            return _proxy.get();
        }

        virtual FakeitContext &getFakeIt() override {
            return _fakeit;
        }

        template<class DATA_TYPE, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
        DataMemberStubbingRoot<C, DATA_TYPE> stubDataMember(DATA_TYPE T::*member, const arglist &... ctorargs) {
            _proxy.stubDataMember(member, ctorargs...);
            return DataMemberStubbingRoot<T, DATA_TYPE>();
        }

        template<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<std::is_base_of<T, C>::value>::type>
        MockingContext<R, arglist...> stubMethod(R(T::*vMethod)(arglist...)) {
            return MockingContext<R, arglist...>(new UniqueMethodMockingContextImpl < id, R, arglist... >
                   (*this, vMethod));
        }

        DtorMockingContext stubDtor() {
            return DtorMockingContext(new DtorMockingContextImpl(*this));
        }







    private:









		std::shared_ptr<FakeObject<C, baseclasses...>> _instanceOwner;
		DynamicProxy<C, baseclasses...> _proxy;
        FakeitContext &_fakeit;

        MockImpl(FakeitContext &fakeit, C &obj, bool isSpy)
                : _instanceOwner(isSpy ? nullptr : asFakeObject(&obj))
				, _proxy{obj}
				, _fakeit(fakeit) {}

        static FakeObject<C, baseclasses...>* asFakeObject(void* instance){
            return reinterpret_cast<FakeObject<C, baseclasses...> *>(instance);
        }

        template<typename R, typename ... arglist>
        class MethodMockingContextBase : public MethodMockingContext<R, arglist...>::Context {
        protected:
            MockImpl<C, baseclasses...> &_mock;

            virtual RecordedMethodBody<R, arglist...> &getRecordedMethodBody() = 0;

        public:
            MethodMockingContextBase(MockImpl<C, baseclasses...> &mock) : _mock(mock) { }

            virtual ~MethodMockingContextBase() = default;

            void addMethodInvocationHandler(typename ActualInvocation<arglist...>::Matcher *matcher,
                ActualInvocationHandler<R, arglist...> *invocationHandler) {
                getRecordedMethodBody().addMethodInvocationHandler(matcher, invocationHandler);
            }

            void scanActualInvocations(const std::function<void(ActualInvocation<arglist...> &)> &scanner) {
                getRecordedMethodBody().scanActualInvocations(scanner);
            }

            void setMethodDetails(std::string mockName, std::string methodName) {
                getRecordedMethodBody().setMethodDetails(mockName, methodName);
            }

            bool isOfMethod(MethodInfo &method) {
                return getRecordedMethodBody().isOfMethod(method);
            }

            ActualInvocationsSource &getInvolvedMock() {
                return _mock;
            }

            std::string getMethodName() {
                return getRecordedMethodBody().getMethod().name();
            }

        };

        template<typename R, typename ... arglist>
        class MethodMockingContextImpl : public MethodMockingContextBase<R, arglist...> {
        protected:

            R (C::*_vMethod)(arglist...);

        public:
            virtual ~MethodMockingContextImpl() = default;

            MethodMockingContextImpl(MockImpl<C, baseclasses...> &mock, R (C::*vMethod)(arglist...))
                    : MethodMockingContextBase<R, arglist...>(mock), _vMethod(vMethod) {
            }


            virtual std::function<R(arglist&...)> getOriginalMethod() override {
                void *mPtr = MethodMockingContextBase<R, arglist...>::_mock.getOriginalMethod(_vMethod);
                C * instance = &(MethodMockingContextBase<R, arglist...>::_mock.get());
                return [=](arglist&... args) -> R {
                    auto m = union_cast<typename VTableMethodType<R,arglist...>::type>(mPtr);
                    return m(instance, std::forward<arglist>(args)...);
                };
            }
        };


        template<int id, typename R, typename ... arglist>
        class UniqueMethodMockingContextImpl : public MethodMockingContextImpl<R, arglist...> {
        protected:

            virtual RecordedMethodBody<R, arglist...> &getRecordedMethodBody() override {
                return MethodMockingContextBase<R, arglist...>::_mock.template stubMethodIfNotStubbed<id>(
                        MethodMockingContextBase<R, arglist...>::_mock._proxy,
                        MethodMockingContextImpl<R, arglist...>::_vMethod);
            }

        public:

            UniqueMethodMockingContextImpl(MockImpl<C, baseclasses...> &mock, R (C::*vMethod)(arglist...))
                    : MethodMockingContextImpl<R, arglist...>(mock, vMethod) {
            }
        };

        class DtorMockingContextImpl : public MethodMockingContextBase<void> {

        protected:

            virtual RecordedMethodBody<void> &getRecordedMethodBody() override {
                return MethodMockingContextBase<void>::_mock.stubDtorIfNotStubbed(
                        MethodMockingContextBase<void>::_mock._proxy);
            }

        public:
            virtual ~DtorMockingContextImpl() = default;

            DtorMockingContextImpl(MockImpl<C, baseclasses...> &mock)
                    : MethodMockingContextBase<void>(mock) {
            }

            virtual std::function<void()> getOriginalMethod() override {
                C &instance = MethodMockingContextBase<void>::_mock.get();
                return [=, &instance]() -> void {
                };
            }

        };

        static MockImpl<C, baseclasses...> *getMockImpl(void *instance) {
            FakeObject<C, baseclasses...> *fake = asFakeObject(instance);
            MockImpl<C, baseclasses...> *mock = reinterpret_cast<MockImpl<C, baseclasses...> *>(fake->getVirtualTable().getCookie(
                    1));
            return mock;
        }

        bool isOwner(){ return _instanceOwner != nullptr;}

		void unmockedDtor() {}

        void unmocked() {
            ActualInvocation<> invocation(Invocation::nextInvocationOrdinal(), UnknownMethod::instance());
            UnexpectedMethodCallEvent event(UnexpectedType::Unmocked, invocation);
            auto &fakeit = getMockImpl(this)->_fakeit;
            fakeit.handle(event);

            std::string format = fakeit.format(event);
            UnexpectedMethodCallException e(format);
            throw e;
        }

        static C *createFakeInstance() {
            FakeObject<C, baseclasses...> *fake = new FakeObject<C, baseclasses...>();
            void *unmockedMethodStubPtr = union_cast<void *>(&MockImpl<C, baseclasses...>::unmocked);
			void *unmockedDtorStubPtr = union_cast<void *>(&MockImpl<C, baseclasses...>::unmockedDtor);
			fake->getVirtualTable().initAll(unmockedMethodStubPtr);
			if (VTUtils::hasVirtualDestructor<C>())
				fake->setDtor(unmockedDtorStubPtr);
			return reinterpret_cast<C *>(fake);
        }

        template<typename R, typename ... arglist>
        void *getOriginalMethod(R (C::*vMethod)(arglist...)) {
            auto vt = _proxy.getOriginalVT();
            auto offset = VTUtils::getOffset(vMethod);
            void *origMethodPtr = vt.getMethod(offset);
            return origMethodPtr;
        }

        void *getOriginalDtor() {
            auto vt = _proxy.getOriginalVT();
            auto offset = VTUtils::getDestructorOffset<C>();
            void *origMethodPtr = vt.getMethod(offset);
            return origMethodPtr;
        }

        template<unsigned int id, typename R, typename ... arglist>
        RecordedMethodBody<R, arglist...> &stubMethodIfNotStubbed(DynamicProxy<C, baseclasses...> &proxy,
                                                                  R (C::*vMethod)(arglist...)) {
            if (!proxy.isMethodStubbed(vMethod)) {
                proxy.template stubMethod<id>(vMethod, createRecordedMethodBody < R, arglist... > (*this, vMethod));
            }
            Destructible *d = proxy.getMethodMock(vMethod);
            RecordedMethodBody<R, arglist...> *methodMock = dynamic_cast<RecordedMethodBody<R, arglist...> *>(d);
            return *methodMock;
        }

        RecordedMethodBody<void> &stubDtorIfNotStubbed(DynamicProxy<C, baseclasses...> &proxy) {
            if (!proxy.isDtorStubbed()) {
                proxy.stubDtor(createRecordedDtorBody(*this));
            }
            Destructible *d = proxy.getDtorMock();
            RecordedMethodBody<void> *dtorMock = dynamic_cast<RecordedMethodBody<void> *>(d);
            return *dtorMock;
        }

        template<typename R, typename ... arglist>
        static RecordedMethodBody<R, arglist...> *createRecordedMethodBody(MockObject<C> &mock,
                                                                           R(C::*vMethod)(arglist...)) {
            return new RecordedMethodBody<R, arglist...>(mock.getFakeIt(), typeid(vMethod).name());
        }

        static RecordedMethodBody<void> *createRecordedDtorBody(MockObject<C> &mock) {
            return new RecordedMethodBody<void>(mock.getFakeIt(), "dtor");
        }
    };
}
namespace fakeit {

    template<typename R, typename... Args>
    struct Prototype;

    template<typename R, typename... Args>
    struct Prototype<R(Args...)> {

        typedef R Type(Args...);

        typedef R ConstType(Args...) const;

        template<class C>
        struct MemberType {

            typedef Type(C::*type);
            typedef ConstType(C::*cosntType);

            static type get(type t) {
                return t;
            }

            static cosntType getconst(cosntType t) {
                return t;
            }

        };

    };

    template<int X, typename R, typename C, typename... arglist>
    struct UniqueMethod {
        R (C::*method)(arglist...);

        UniqueMethod(R (C::*vMethod)(arglist...)) : method(vMethod) { }

        int uniqueId() {
            return X;
        }




    };

}


namespace fakeit {
    namespace internal {
    }
    using namespace fakeit::internal;

    template<typename C, typename ... baseclasses>
    class Mock : public ActualInvocationsSource {
        MockImpl<C, baseclasses...> impl;
    public:
        virtual ~Mock() = default;

        static_assert(std::is_polymorphic<C>::value, "Can only mock a polymorphic type");

        Mock() : impl(Fakeit) {
        }

        explicit Mock(C &obj) : impl(Fakeit, obj) {
        }

        virtual C &get() {
            return impl.get();
        }





		C &operator()() {
            return get();
        }

        void Reset() {
            impl.reset();
        }

		void ClearInvocationHistory() {
			impl.clear();
		}

        template<class DATA_TYPE, typename ... arglist,
                class = typename std::enable_if<std::is_member_object_pointer<DATA_TYPE C::*>::value>::type>
        DataMemberStubbingRoot<C, DATA_TYPE> Stub(DATA_TYPE C::* member, const arglist &... ctorargs) {
            return impl.stubDataMember(member, ctorargs...);
        }

        template<int id, typename R, typename T, typename ... arglist, class = typename std::enable_if<
                !std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<R, arglist...> stub(R (T::*vMethod)(arglist...) const) {
            auto methodWithoutConstVolatile = reinterpret_cast<R (T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                !std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
            auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                !std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
            auto methodWithoutConstVolatile = reinterpret_cast<R(T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                !std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<R, arglist...> stub(R(T::*vMethod)(arglist...)) {
            return impl.template stubMethod<id>(vMethod);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) const) {
            auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) volatile) {
            auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...) const volatile) {
            auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        template<int id, typename R, typename T, typename... arglist, class = typename std::enable_if<
                std::is_void<R>::value && std::is_base_of<T, C>::value>::type>
        MockingContext<void, arglist...> stub(R(T::*vMethod)(arglist...)) {
            auto methodWithoutConstVolatile = reinterpret_cast<void (T::*)(arglist...)>(vMethod);
            return impl.template stubMethod<id>(methodWithoutConstVolatile);
        }

        DtorMockingContext dtor() {
            return impl.stubDtor();
        }

        void getActualInvocations(std::unordered_set<Invocation *> &into) const override {
            impl.getActualInvocations(into);
        }

    };

}

#include <exception>

namespace fakeit {

    class RefCount {
    private:
        int count;

    public:
        void AddRef() {
            count++;
        }

        int Release() {
            return --count;
        }
    };

    template<typename T>
    class smart_ptr {
    private:
        T *pData;
        RefCount *reference;

    public:
        smart_ptr() : pData(0), reference(0) {
            reference = new RefCount();
            reference->AddRef();
        }

        smart_ptr(T *pValue) : pData(pValue), reference(0) {
            reference = new RefCount();
            reference->AddRef();
        }

        smart_ptr(const smart_ptr<T> &sp) : pData(sp.pData), reference(sp.reference) {
            reference->AddRef();
        }

        ~smart_ptr() THROWS {
            if (reference->Release() == 0) {
                delete reference;
                delete pData;
            }
        }

        T &operator*() {
            return *pData;
        }

        T *operator->() {
            return pData;
        }

        smart_ptr<T> &operator=(const smart_ptr<T> &sp) {
            if (this != &sp) {


                if (reference->Release() == 0) {
                    delete reference;
                    delete pData;
                }



                pData = sp.pData;
                reference = sp.reference;
                reference->AddRef();
            }
            return *this;
        }
    };

}

namespace fakeit {

    class WhenFunctor {

        struct StubbingChange {

            friend class WhenFunctor;

            virtual ~StubbingChange() THROWS {

                if (std::uncaught_exception()) {
                    return;
                }

                _xaction.commit();
            }

            StubbingChange(StubbingChange &other) :
                    _xaction(other._xaction) {
            }

        private:

            StubbingChange(Xaction &xaction)
                    : _xaction(xaction) {
            }

            Xaction &_xaction;
        };

    public:

        template<typename R, typename ... arglist>
        struct MethodProgress : MethodStubbingProgress<R, arglist...> {

            friend class WhenFunctor;

            virtual ~MethodProgress() override = default;

            MethodProgress(MethodProgress &other) :
                    _progress(other._progress), _context(other._context) {
            }

            MethodProgress(StubbingContext<R, arglist...> &xaction) :
                    _progress(new StubbingChange(xaction)), _context(xaction) {
            }

        protected:

            virtual MethodStubbingProgress<R, arglist...> &DoImpl(Action<R, arglist...> *action) override {
                _context.appendAction(action);
                return *this;
            }

        private:
            smart_ptr<StubbingChange> _progress;
            StubbingContext<R, arglist...> &_context;
        };


        WhenFunctor() {
        }

        template<typename R, typename ... arglist>
        MethodProgress<R, arglist...> operator()(const StubbingContext<R, arglist...> &stubbingContext) {
            StubbingContext<R, arglist...> &rootWithoutConst = const_cast<StubbingContext<R, arglist...> &>(stubbingContext);
            MethodProgress<R, arglist...> progress(rootWithoutConst);
            return progress;
        }

    };

}
namespace fakeit {

    class FakeFunctor {
    private:
        template<typename R, typename ... arglist>
        void fake(const StubbingContext<R, arglist...> &root) {
            StubbingContext<R, arglist...> &rootWithoutConst = const_cast<StubbingContext<R, arglist...> &>(root);
            rootWithoutConst.appendAction(new ReturnDefaultValue<R, arglist...>());
            rootWithoutConst.commit();
        }

        void operator()() {
        }

    public:

        template<typename H, typename ... M>
        void operator()(const H &head, const M &... tail) {
            fake(head);
            this->operator()(tail...);
        }

    };

}
#include <set>
#include <set>


namespace fakeit {

    struct InvocationUtils {

        static void sortByInvocationOrder(std::unordered_set<Invocation *> &ivocations,
                                          std::vector<Invocation *> &result) {
            auto comparator = [](Invocation *a, Invocation *b) -> bool {
                return a->getOrdinal() < b->getOrdinal();
            };
            std::set<Invocation *, bool (*)(Invocation *a, Invocation *b)> sortedIvocations(comparator);
            for (auto i : ivocations)
                sortedIvocations.insert(i);

            for (auto i : sortedIvocations)
                result.push_back(i);
        }

        static void collectActualInvocations(std::unordered_set<Invocation *> &actualInvocations,
                                             std::vector<ActualInvocationsSource *> &invocationSources) {
            for (auto source : invocationSources) {
                source->getActualInvocations(actualInvocations);
            }
        }

        static void selectNonVerifiedInvocations(std::unordered_set<Invocation *> &actualInvocations,
                                                 std::unordered_set<Invocation *> &into) {
            for (auto invocation : actualInvocations) {
                if (!invocation->isVerified()) {
                    into.insert(invocation);
                }
            }
        }

        static void collectInvocationSources(std::vector<ActualInvocationsSource *> &) {
        }

        template<typename ... list>
        static void collectInvocationSources(std::vector<ActualInvocationsSource *> &into,
                                             const ActualInvocationsSource &mock,
                                             const list &... tail) {
            into.push_back(const_cast<ActualInvocationsSource *>(&mock));
            collectInvocationSources(into, tail...);
        }

        static void collectSequences(std::vector<Sequence *> &) {
        }

        template<typename ... list>
        static void collectSequences(std::vector<Sequence *> &vec, const Sequence &sequence, const list &... tail) {
            vec.push_back(&const_cast<Sequence &>(sequence));
            collectSequences(vec, tail...);
        }

        static void collectInvolvedMocks(std::vector<Sequence *> &allSequences,
                                         std::vector<ActualInvocationsSource *> &involvedMocks) {
            for (auto sequence : allSequences) {
                sequence->getInvolvedMocks(involvedMocks);
            }
        }

        template<class T>
        static T &remove_const(const T &s) {
            return const_cast<T &>(s);
        }

    };

}

#include <memory>

#include <vector>
#include <unordered_set>

namespace fakeit {
    struct MatchAnalysis {
        std::vector<Invocation *> actualSequence;
        std::vector<Invocation *> matchedInvocations;
        int count;

        void run(InvocationsSourceProxy &involvedInvocationSources, std::vector<Sequence *> &expectedPattern) {
            getActualInvocationSequence(involvedInvocationSources, actualSequence);
            count = countMatches(expectedPattern, actualSequence, matchedInvocations);
        }

    private:
        static void getActualInvocationSequence(InvocationsSourceProxy &involvedMocks,
                                                std::vector<Invocation *> &actualSequence) {
            std::unordered_set<Invocation *> actualInvocations;
            collectActualInvocations(involvedMocks, actualInvocations);
            InvocationUtils::sortByInvocationOrder(actualInvocations, actualSequence);
        }

        static int countMatches(std::vector<Sequence *> &pattern, std::vector<Invocation *> &actualSequence,
                                std::vector<Invocation *> &matchedInvocations) {
            int end = -1;
            int count = 0;
            int startSearchIndex = 0;
            while (findNextMatch(pattern, actualSequence, startSearchIndex, end, matchedInvocations)) {
                count++;
                startSearchIndex = end;
            }
            return count;
        }

        static void collectActualInvocations(InvocationsSourceProxy &involvedMocks,
                                             std::unordered_set<Invocation *> &actualInvocations) {
            involvedMocks.getActualInvocations(actualInvocations);
        }

        static bool findNextMatch(std::vector<Sequence *> &pattern, std::vector<Invocation *> &actualSequence,
                                  int startSearchIndex, int &end,
                                  std::vector<Invocation *> &matchedInvocations) {
            for (auto sequence : pattern) {
                int index = findNextMatch(sequence, actualSequence, startSearchIndex);
                if (index == -1) {
                    return false;
                }
                collectMatchedInvocations(actualSequence, matchedInvocations, index, sequence->size());
                startSearchIndex = index + sequence->size();
            }
            end = startSearchIndex;
            return true;
        }


        static void collectMatchedInvocations(std::vector<Invocation *> &actualSequence,
                                              std::vector<Invocation *> &matchedInvocations, int start,
                                              int length) {
            int indexAfterMatchedPattern = start + length;
            for (; start < indexAfterMatchedPattern; start++) {
                matchedInvocations.push_back(actualSequence[start]);
            }
        }


        static bool isMatch(std::vector<Invocation *> &actualSequence,
                            std::vector<Invocation::Matcher *> &expectedSequence, int start) {
            bool found = true;
            for (unsigned int j = 0; found && j < expectedSequence.size(); j++) {
                Invocation *actual = actualSequence[start + j];
                Invocation::Matcher *expected = expectedSequence[j];
                found = found && expected->matches(*actual);
            }
            return found;
        }

        static int findNextMatch(Sequence *&pattern, std::vector<Invocation *> &actualSequence, int startSearchIndex) {
            std::vector<Invocation::Matcher *> expectedSequence;
            pattern->getExpectedSequence(expectedSequence);
            for (int i = startSearchIndex; i < ((int) actualSequence.size() - (int) expectedSequence.size() + 1); i++) {
                if (isMatch(actualSequence, expectedSequence, i)) {
                    return i;
                }
            }
            return -1;
        }

    };
}

namespace fakeit {

    struct SequenceVerificationExpectation {

        friend class SequenceVerificationProgress;

        ~SequenceVerificationExpectation() THROWS {
            if (std::uncaught_exception()) {
                return;
            }
            VerifyExpectation(_fakeit);
        }

        void setExpectedPattern(std::vector<Sequence *> expectedPattern) {
            _expectedPattern = expectedPattern;
        }

        void setExpectedCount(const int count) {
            _expectedCount = count;
        }

        void setFileInfo(const char * file, int line, const char * callingMethod) {
            _file = file;
            _line = line;
            _testMethod = callingMethod;
        }

    private:

        VerificationEventHandler &_fakeit;
        InvocationsSourceProxy _involvedInvocationSources;
        std::vector<Sequence *> _expectedPattern;
        int _expectedCount;

        const char * _file;
        int _line;
		const char * _testMethod;
        bool _isVerified;

        SequenceVerificationExpectation(
                VerificationEventHandler &fakeit,
                InvocationsSourceProxy mocks,
                std::vector<Sequence *> &expectedPattern) :
                _fakeit(fakeit),
                _involvedInvocationSources(mocks),
                _expectedPattern(expectedPattern),
                _expectedCount(-1),
                _line(0),
                _isVerified(false) {
        }


        void VerifyExpectation(VerificationEventHandler &verificationErrorHandler) {
            if (_isVerified)
                return;
            _isVerified = true;

            MatchAnalysis ma;
            ma.run(_involvedInvocationSources, _expectedPattern);

            if (isAtLeastVerification() && atLeastLimitNotReached(ma.count)) {
                return handleAtLeastVerificationEvent(verificationErrorHandler, ma.actualSequence, ma.count);
            }

            if (isExactVerification() && exactLimitNotMatched(ma.count)) {
                return handleExactVerificationEvent(verificationErrorHandler, ma.actualSequence, ma.count);
            }

            markAsVerified(ma.matchedInvocations);
        }

        std::vector<Sequence *> &collectSequences(std::vector<Sequence *> &vec) {
            return vec;
        }

        template<typename ... list>
        std::vector<Sequence *> &collectSequences(std::vector<Sequence *> &vec, const Sequence &sequence,
                                                  const list &... tail) {
            vec.push_back(&const_cast<Sequence &>(sequence));
            return collectSequences(vec, tail...);
        }


        static void markAsVerified(std::vector<Invocation *> &matchedInvocations) {
            for (auto i : matchedInvocations) {
                i->markAsVerified();
            }
        }

        bool isAtLeastVerification() {

            return _expectedCount < 0;
        }

        bool isExactVerification() {
            return !isAtLeastVerification();
        }

        bool atLeastLimitNotReached(int actualCount) {
            return actualCount < -_expectedCount;
        }

        bool exactLimitNotMatched(int actualCount) {
            return actualCount != _expectedCount;
        }

        void handleExactVerificationEvent(VerificationEventHandler &verificationErrorHandler,
                                          std::vector<Invocation *> actualSequence, int count) {
            SequenceVerificationEvent evt(VerificationType::Exact, _expectedPattern, actualSequence, _expectedCount,
                                          count);
            evt.setFileInfo(_file, _line, _testMethod);
            return verificationErrorHandler.handle(evt);
        }

        void handleAtLeastVerificationEvent(VerificationEventHandler &verificationErrorHandler,
                                            std::vector<Invocation *> actualSequence, int count) {
            SequenceVerificationEvent evt(VerificationType::AtLeast, _expectedPattern, actualSequence, -_expectedCount,
                                          count);
            evt.setFileInfo(_file, _line, _testMethod);
            return verificationErrorHandler.handle(evt);
        }

    };

}
namespace fakeit {
    class ThrowFalseEventHandler : public VerificationEventHandler {

        void handle(const SequenceVerificationEvent &) override {
            throw false;
        }

        void handle(const NoMoreInvocationsVerificationEvent &) override {
            throw false;
        }
    };
}


namespace fakeit {

    struct FakeitContext;

    class SequenceVerificationProgress {

        friend class UsingFunctor;

        friend class VerifyFunctor;

        friend class UsingProgress;

        smart_ptr<SequenceVerificationExpectation> _expectationPtr;

        SequenceVerificationProgress(SequenceVerificationExpectation *ptr) : _expectationPtr(ptr) {
        }

        SequenceVerificationProgress(
                FakeitContext &fakeit,
                InvocationsSourceProxy sources,
                std::vector<Sequence *> &allSequences) :
                SequenceVerificationProgress(new SequenceVerificationExpectation(fakeit, sources, allSequences)) {
        }

        virtual void verifyInvocations(const int times) {
            _expectationPtr->setExpectedCount(times);
        }

        class Terminator {
            smart_ptr<SequenceVerificationExpectation> _expectationPtr;

            bool toBool() {
                try {
                    ThrowFalseEventHandler eh;
                    _expectationPtr->VerifyExpectation(eh);
                    return true;
                }
                catch (bool e) {
                    return e;
                }
            }

        public:
            Terminator(smart_ptr<SequenceVerificationExpectation> expectationPtr) : _expectationPtr(expectationPtr) { };

            operator bool() {
                return toBool();
            }

            bool operator!() const { return !const_cast<Terminator *>(this)->toBool(); }
        };

    public:

        ~SequenceVerificationProgress() THROWS { };

        operator bool() const {
            return Terminator(_expectationPtr);
        }

        bool operator!() const { return !Terminator(_expectationPtr); }

        Terminator Never() {
            Exactly(0);
            return Terminator(_expectationPtr);
        }

        Terminator Once() {
            Exactly(1);
            return Terminator(_expectationPtr);
        }

        Terminator Twice() {
            Exactly(2);
            return Terminator(_expectationPtr);
        }

        Terminator AtLeastOnce() {
            verifyInvocations(-1);
            return Terminator(_expectationPtr);
        }

        Terminator Exactly(const int times) {
            if (times < 0) {
                throw std::invalid_argument(std::string("bad argument times:").append(fakeit::to_string(times)));
            }
            verifyInvocations(times);
            return Terminator(_expectationPtr);
        }

        Terminator Exactly(const Quantity &q) {
            Exactly(q.quantity);
            return Terminator(_expectationPtr);
        }

        Terminator AtLeast(const int times) {
            if (times < 0) {
                throw std::invalid_argument(std::string("bad argument times:").append(fakeit::to_string(times)));
            }
            verifyInvocations(-times);
            return Terminator(_expectationPtr);
        }

        Terminator AtLeast(const Quantity &q) {
            AtLeast(q.quantity);
            return Terminator(_expectationPtr);
        }

        SequenceVerificationProgress setFileInfo(const char * file, int line, const char * callingMethod) {
            _expectationPtr->setFileInfo(file, line, callingMethod);
            return *this;
        }
    };
}

namespace fakeit {

    class UsingProgress {
        fakeit::FakeitContext &_fakeit;
        InvocationsSourceProxy _sources;

        void collectSequences(std::vector<fakeit::Sequence *> &) {
        }

        template<typename ... list>
        void collectSequences(std::vector<fakeit::Sequence *> &vec, const fakeit::Sequence &sequence,
                              const list &... tail) {
            vec.push_back(&const_cast<fakeit::Sequence &>(sequence));
            collectSequences(vec, tail...);
        }

    public:

        UsingProgress(fakeit::FakeitContext &fakeit, InvocationsSourceProxy source) :
                _fakeit(fakeit),
                _sources(source) {
        }

        template<typename ... list>
        SequenceVerificationProgress Verify(const fakeit::Sequence &sequence, const list &... tail) {
            std::vector<fakeit::Sequence *> allSequences;
            collectSequences(allSequences, sequence, tail...);
            SequenceVerificationProgress progress(_fakeit, _sources, allSequences);
            return progress;
        }

    };
}

namespace fakeit {

    class UsingFunctor {

        friend class VerifyFunctor;

        FakeitContext &_fakeit;

    public:

        UsingFunctor(FakeitContext &fakeit) : _fakeit(fakeit) {
        }

        template<typename ... list>
        UsingProgress operator()(const ActualInvocationsSource &head, const list &... tail) {
            std::vector<ActualInvocationsSource *> allMocks{&InvocationUtils::remove_const(head),
                                                            &InvocationUtils::remove_const(tail)...};
            InvocationsSourceProxy aggregateInvocationsSource{new AggregateInvocationsSource(allMocks)};
            UsingProgress progress(_fakeit, aggregateInvocationsSource);
            return progress;
        }

    };
}
#include <set>

namespace fakeit {

    class VerifyFunctor {

        FakeitContext &_fakeit;


    public:

        VerifyFunctor(FakeitContext &fakeit) : _fakeit(fakeit) {
        }

        template<typename ... list>
        SequenceVerificationProgress operator()(const Sequence &sequence, const list &... tail) {
            std::vector<Sequence *> allSequences{&InvocationUtils::remove_const(sequence),
                                                 &InvocationUtils::remove_const(tail)...};

            std::vector<ActualInvocationsSource *> involvedSources;
            InvocationUtils::collectInvolvedMocks(allSequences, involvedSources);
            InvocationsSourceProxy aggregateInvocationsSource{new AggregateInvocationsSource(involvedSources)};

            UsingProgress usingProgress(_fakeit, aggregateInvocationsSource);
            return usingProgress.Verify(sequence, tail...);
        }

    };

}
#include <set>
#include <memory>
namespace fakeit {

    class VerifyNoOtherInvocationsVerificationProgress {

        friend class VerifyNoOtherInvocationsFunctor;

        struct VerifyNoOtherInvocationsExpectation {

            friend class VerifyNoOtherInvocationsVerificationProgress;

            ~VerifyNoOtherInvocationsExpectation() THROWS {
                if (std::uncaught_exception()) {
                    return;
                }

                VerifyExpectation(_fakeit);
            }

            void setFileInfo(const char * file, int line, const char * callingMethod) {
                _file = file;
                _line = line;
                _callingMethod = callingMethod;
            }

        private:

            VerificationEventHandler &_fakeit;
            std::vector<ActualInvocationsSource *> _mocks;

			const char * _file;
            int _line;
			const char * _callingMethod;
            bool _isVerified;

            VerifyNoOtherInvocationsExpectation(VerificationEventHandler &fakeit,
                                                std::vector<ActualInvocationsSource *> mocks) :
                    _fakeit(fakeit),
                    _mocks(mocks),
                    _line(0),
                    _isVerified(false) {
            }

            VerifyNoOtherInvocationsExpectation(VerifyNoOtherInvocationsExpectation &other) = default;

            void VerifyExpectation(VerificationEventHandler &verificationErrorHandler) {
                if (_isVerified)
                    return;
                _isVerified = true;

                std::unordered_set<Invocation *> actualInvocations;
                InvocationUtils::collectActualInvocations(actualInvocations, _mocks);

                std::unordered_set<Invocation *> nonVerifiedInvocations;
                InvocationUtils::selectNonVerifiedInvocations(actualInvocations, nonVerifiedInvocations);

                if (nonVerifiedInvocations.size() > 0) {
                    std::vector<Invocation *> sortedNonVerifiedInvocations;
                    InvocationUtils::sortByInvocationOrder(nonVerifiedInvocations, sortedNonVerifiedInvocations);

                    std::vector<Invocation *> sortedActualInvocations;
                    InvocationUtils::sortByInvocationOrder(actualInvocations, sortedActualInvocations);

                    NoMoreInvocationsVerificationEvent evt(sortedActualInvocations, sortedNonVerifiedInvocations);
                    evt.setFileInfo(_file, _line, _callingMethod);
                    return verificationErrorHandler.handle(evt);
                }
            }

        };

        fakeit::smart_ptr<VerifyNoOtherInvocationsExpectation> _ptr;

        VerifyNoOtherInvocationsVerificationProgress(VerifyNoOtherInvocationsExpectation *ptr) :
                _ptr(ptr) {
        }

        VerifyNoOtherInvocationsVerificationProgress(FakeitContext &fakeit,
                                                     std::vector<ActualInvocationsSource *> &invocationSources)
                : VerifyNoOtherInvocationsVerificationProgress(
                new VerifyNoOtherInvocationsExpectation(fakeit, invocationSources)
        ) {
        }

        bool toBool() {
            try {
                ThrowFalseEventHandler ev;
                _ptr->VerifyExpectation(ev);
                return true;
            }
            catch (bool e) {
                return e;
            }
        }

    public:


        ~VerifyNoOtherInvocationsVerificationProgress() THROWS {
        };

        VerifyNoOtherInvocationsVerificationProgress setFileInfo(const char * file, int line,
			const char * callingMethod) {
            _ptr->setFileInfo(file, line, callingMethod);
            return *this;
        }

        operator bool() const {
            return const_cast<VerifyNoOtherInvocationsVerificationProgress *>(this)->toBool();
        }

        bool operator!() const { return !const_cast<VerifyNoOtherInvocationsVerificationProgress *>(this)->toBool(); }

    };

}


namespace fakeit {
    class VerifyNoOtherInvocationsFunctor {

        FakeitContext &_fakeit;

    public:

        VerifyNoOtherInvocationsFunctor(FakeitContext &fakeit) : _fakeit(fakeit) {
        }

        void operator()() {
        }

        template<typename ... list>
        VerifyNoOtherInvocationsVerificationProgress operator()(const ActualInvocationsSource &head,
                                                                const list &... tail) {
            std::vector<ActualInvocationsSource *> invocationSources{&InvocationUtils::remove_const(head),
                                                                     &InvocationUtils::remove_const(tail)...};
            VerifyNoOtherInvocationsVerificationProgress progress{_fakeit, invocationSources};
            return progress;
        }
    };

}
namespace fakeit {

    class SpyFunctor {
    private:

        template<typename R, typename ... arglist>
        void spy(const SpyingContext<R, arglist...> &root) {
            SpyingContext<R, arglist...> &rootWithoutConst = const_cast<SpyingContext<R, arglist...> &>(root);
            auto methodFromOriginalVT = rootWithoutConst.getOriginalMethod();
            rootWithoutConst.appendAction(new ReturnDelegateValue<R, arglist...>(methodFromOriginalVT));
            rootWithoutConst.commit();
        }

        void operator()() {
        }

    public:

        template<typename H, typename ... M>
        void operator()(const H &head, const M &... tail) {
            spy(head);
            this->operator()(tail...);
        }

    };

}

#include <vector>
#include <set>

namespace fakeit {
    class VerifyUnverifiedFunctor {

        FakeitContext &_fakeit;

    public:

        VerifyUnverifiedFunctor(FakeitContext &fakeit) : _fakeit(fakeit) {
        }

        template<typename ... list>
        SequenceVerificationProgress operator()(const Sequence &sequence, const list &... tail) {
            std::vector<Sequence *> allSequences{&InvocationUtils::remove_const(sequence),
                                                 &InvocationUtils::remove_const(tail)...};

            std::vector<ActualInvocationsSource *> involvedSources;
            InvocationUtils::collectInvolvedMocks(allSequences, involvedSources);

            InvocationsSourceProxy aggregateInvocationsSource{new AggregateInvocationsSource(involvedSources)};
            InvocationsSourceProxy unverifiedInvocationsSource{
                    new UnverifiedInvocationsSource(aggregateInvocationsSource)};

            UsingProgress usingProgress(_fakeit, unverifiedInvocationsSource);
            return usingProgress.Verify(sequence, tail...);
        }

    };

    class UnverifiedFunctor {
    public:
        UnverifiedFunctor(FakeitContext &fakeit) : Verify(fakeit) {
        }

        VerifyUnverifiedFunctor Verify;

        template<typename ... list>
        UnverifiedInvocationsSource operator()(const ActualInvocationsSource &head, const list &... tail) {
            std::vector<ActualInvocationsSource *> allMocks{&InvocationUtils::remove_const(head),
                                                            &InvocationUtils::remove_const(tail)...};
            InvocationsSourceProxy aggregateInvocationsSource{new AggregateInvocationsSource(allMocks)};
            UnverifiedInvocationsSource unverifiedInvocationsSource{aggregateInvocationsSource};
            return unverifiedInvocationsSource;
        }













    };
}

namespace fakeit {

    static UsingFunctor Using(Fakeit);
    static VerifyFunctor Verify(Fakeit);
    static VerifyNoOtherInvocationsFunctor VerifyNoOtherInvocations(Fakeit);
    static UnverifiedFunctor Unverified(Fakeit);
    static SpyFunctor Spy;
    static FakeFunctor Fake;
    static WhenFunctor When;

    template<class T>
    class SilenceUnusedVariableWarnings {

        void use(void *) {
        }

        SilenceUnusedVariableWarnings() {
            use(&Fake);
            use(&When);
            use(&Spy);
            use(&Using);
            use(&Verify);
            use(&VerifyNoOtherInvocations);
            use(&_);
        }
    };

}
#ifdef _MSC_VER
#define __func__ __FUNCTION__
#endif

#define MOCK_TYPE(mock) \
    std::remove_reference<decltype(mock.get())>::type

#define OVERLOADED_METHOD_PTR(mock, method, prototype) \
    fakeit::Prototype<prototype>::MemberType<MOCK_TYPE(mock)>::get(&MOCK_TYPE(mock)::method)

#define CONST_OVERLOADED_METHOD_PTR(mock, method, prototype) \
    fakeit::Prototype<prototype>::MemberType<MOCK_TYPE(mock)>::getconst(&MOCK_TYPE(mock)::method)

#define Dtor(mock) \
    mock.dtor().setMethodDetails(#mock,"destructor")

#define Method(mock, method) \
    mock.template stub<__COUNTER__>(&MOCK_TYPE(mock)::method).setMethodDetails(#mock,#method)

#define OverloadedMethod(mock, method, prototype) \
    mock.template stub<__COUNTER__>(OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)

#define ConstOverloadedMethod(mock, method, prototype) \
    mock.template stub<__COUNTER__>(CONST_OVERLOADED_METHOD_PTR( mock , method, prototype )).setMethodDetails(#mock,#method)

#define Verify(...) \
        Verify( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__)

#define Using(...) \
        Using( __VA_ARGS__ )

#define VerifyNoOtherInvocations(...) \
    VerifyNoOtherInvocations( __VA_ARGS__ ).setFileInfo(__FILE__, __LINE__, __func__)

#define Fake(...) \
    Fake( __VA_ARGS__ )

#define When(call) \
    When(call)

#ifdef __clang__
//#    ifdef __ICC // icpc defines the __clang__ macro
//#        pragma warning(pop)
//#    else
//#        pragma clang diagnostic pop
//#    endif
#endif

#if defined __GNUC__
#    pragma GCC diagnostic pop
#endif

#endif
