<commit_before>#ifndef Mock_h__
#define Mock_h__

#include <type_traits>
#include <memory>

#include "mockutils/DynamicProxy.h"
#include "mock4cpp/StubbingImpl.h"
#include "mock4cpp/MockRepository.h"

using namespace mock4cpp;
using namespace mock4cpp::stubbing;
using namespace mock4cpp::verification;

template <typename C>
class Mock : private MockBase
{	
private:
	DynamicProxy<C> instance;

	template <typename R, typename... arglist>
	MethodMock<R, arglist...>& stubMethodIfNotStubbed(DynamicProxy<C> &instance, R(C::*vMethod)(arglist...)){
		if (!instance.isStubbed(vMethod)){
			auto methodMock = std::shared_ptr<MethodInvocationHandler<R, arglist...>>{new MethodMock<R, arglist...>(*this)};
			instance.stubMethod(vMethod, methodMock);
		}
		Destructable * d = instance.getMethodMock(vMethod);
		MethodMock<R, arglist...> * methodMock = reinterpret_cast<MethodMock<R, arglist...> *>(d);
		return *methodMock;
	}

	template <typename R, typename... arglist>
	class StubbingContextImpl : public StubbingContext<R,arglist...> {
		Mock<C>& mock;
		R(C::*vMethod)(arglist...);
	public:
		StubbingContextImpl(Mock<C>& mock, R(C::*vMethod)(arglist...)) :mock(mock),vMethod(vMethod){
		}
		virtual MethodMock<R, arglist...>& getMethodMock() override {
			return mock.stubMethodIfNotStubbed(mock.instance,vMethod);
		}
	};

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot< R, arglist...> StubImpl(R(C::*vMethod)(arglist...)){
		return FunctionStubbingRoot<R, arglist...>(
			std::shared_ptr<StubbingContext <R, arglist...>>(new StubbingContextImpl< R, arglist...>(*this, vMethod)));
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> StubImpl(R(C::*vMethod)(arglist...)){
		return ProcedureStubbingRoot<R, arglist...>(
			std::shared_ptr <StubbingContext<R, arglist...>>(new StubbingContextImpl< R, arglist...>(*this, vMethod)));
	}

	void Stub(){}

	template <class DATA_TYPE, typename... arglist>
	DataMemberStubbingRoot<C, DATA_TYPE> stubDataMember(DATA_TYPE C::*member, const arglist&... ctorargs)
	{
		instance.stubDataMember(member, ctorargs...);
		return DataMemberStubbingRoot<C, DATA_TYPE>();
	}

public:
	static_assert(std::is_polymorphic<C>::value, "Can only mock a polymorphic type");

	Mock() : MockBase{}, instance{ []{ throw UnmockedMethodException{}; } }{
	}
	
	~Mock(){
	}
	
	C& get()
	{
		return instance.get();
	}

	C& operator()()
	{
		return instance.get();
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template < typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...)) {
		return StubImpl(vMethod);
	}

	//		

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...)){
		return StubImpl(vMethod);
	}

	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 stubDataMember(member, ctorargs...);
	}

	template <typename H, typename... M
		, class = typename std::enable_if<std::is_member_function_pointer<H>::value>::type
	>
	void Stub(H head, M... tail) 
	{
		When(head).startStubbing();
		Stub(tail...);
	}




	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template < typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...)) {
		return StubImpl(vMethod);
	}



	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...)){
		return StubImpl(vMethod);
	}

};

class VerifyFunctor
{
public:
	VerifyFunctor() {}
	MethodVerificationProgress& operator() (MethodVerificationProgress& verificationProgress) {
		verificationProgress.startVerification();
		return  verificationProgress;
	}
} static Verify;

class WhenFunctor
{
public:
	WhenFunctor() {}

	template <typename R, typename... arglist>
	FirstProcedureStubbingProgress<R, arglist...>& operator()(const ProcedureStubbingRoot<R, arglist...>& stubbingProgress) {
		return  (FirstProcedureStubbingProgress<R, arglist...>&)stubbingProgress;
	}

	template <typename R, typename... arglist>
	FirstFunctionStubbingProgress<R, arglist...>& operator()(const FunctionStubbingRoot<R, arglist...>& stubbingProgress) {
		return  (FirstFunctionStubbingProgress<R, arglist...>&)stubbingProgress;
	}

} static When;

class StubFunctor
{
private:
	void operator() (){}
public:
	StubFunctor() {}

	template <typename H>
	H& operator() (H& head) {
		//When(head).startStubbing();
		head.startStubbing();
		return head;
	}

	template <typename H, typename... M>
	void operator() (H& head, M&... tail) {
		//When(head).startStubbing();<commit_msg>improve gcc compatability<commit_after>#ifndef Mock_h__
#define Mock_h__

#include <type_traits>
#include <memory>

#include "mockutils/DynamicProxy.h"
#include "mock4cpp/StubbingImpl.h"
#include "mock4cpp/MockRepository.h"

using namespace mock4cpp;
using namespace mock4cpp::stubbing;
using namespace mock4cpp::verification;

template <typename C>
class Mock : private MockBase
{	
private:
	DynamicProxy<C> instance;

	template <typename R, typename... arglist>
	MethodMock<R, arglist...>& stubMethodIfNotStubbed(DynamicProxy<C> &instance, R(C::*vMethod)(arglist...)){
		if (!instance.isStubbed(vMethod)){
			auto methodMock = std::shared_ptr<MethodInvocationHandler<R, arglist...>>{new MethodMock<R, arglist...>(*this)};
			instance.stubMethod(vMethod, methodMock);
		}
		Destructable * d = instance.getMethodMock(vMethod);
		MethodMock<R, arglist...> * methodMock = reinterpret_cast<MethodMock<R, arglist...> *>(d);
		return *methodMock;
	}

	template <typename R, typename... arglist>
	class StubbingContextImpl : public StubbingContext<R,arglist...> {
		Mock<C>& mock;
		R(C::*vMethod)(arglist...);
	public:
		StubbingContextImpl(Mock<C>& mock, R(C::*vMethod)(arglist...)) :mock(mock),vMethod(vMethod){
		}
		virtual MethodMock<R, arglist...>& getMethodMock() override {
			return mock.stubMethodIfNotStubbed(mock.instance,vMethod);
		}
	};

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot< R, arglist...> StubImpl(R(C::*vMethod)(arglist...)){
		return FunctionStubbingRoot<R, arglist...>(
			std::shared_ptr<StubbingContext <R, arglist...>>(new StubbingContextImpl< R, arglist...>(*this, vMethod)));
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> StubImpl(R(C::*vMethod)(arglist...)){
		return ProcedureStubbingRoot<R, arglist...>(
			std::shared_ptr <StubbingContext<R, arglist...>>(new StubbingContextImpl< R, arglist...>(*this, vMethod)));
	}

	void Stub(){}

	template <class DATA_TYPE, typename... arglist>
	DataMemberStubbingRoot<C, DATA_TYPE> stubDataMember(DATA_TYPE C::*member, const arglist&... ctorargs)
	{
		instance.stubDataMember(member, ctorargs...);
		return DataMemberStubbingRoot<C, DATA_TYPE>();
	}

public:
	static_assert(std::is_polymorphic<C>::value, "Can only mock a polymorphic type");

	Mock() : MockBase{}, instance{ []{ throw UnmockedMethodException{}; } }{
	}
	
	~Mock(){
	}
	
	C& get()
	{
		return instance.get();
	}

	C& operator()()
	{
		return instance.get();
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template < typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...)) {
		return StubImpl(vMethod);
	}

	//		

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> When(R(C::*vMethod)(arglist...)){
		return StubImpl(vMethod);
	}

	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 stubDataMember(member, ctorargs...);
	}

	template <typename H, typename... M
		, class = typename std::enable_if<std::is_member_function_pointer<H>::value>::type
	>
	void Stub(H head, M... tail) 
	{
		When(head).startStubbing();
		Stub(tail...);
	}




	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template < typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<!std::is_void<R>::value>::type>
	FunctionStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...)) {
		return StubImpl(vMethod);
	}



	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...) const volatile){
		auto methodWithoutConstVolatile = reinterpret_cast<R(C::*)(arglist...)>(vMethod);
		return StubImpl(methodWithoutConstVolatile);
	}

	template <typename R, typename... arglist, class = typename std::enable_if<std::is_void<R>::value>::type>
	ProcedureStubbingRoot<R, arglist...> operator [](R(C::*vMethod)(arglist...)){
		return StubImpl(vMethod);
	}

};

class VerifyFunctor
{
public:
	VerifyFunctor() {}
	MethodVerificationProgress& operator() (MethodVerificationProgress& verificationProgress) {
		verificationProgress.startVerification();
		return  verificationProgress;
	}
} static Verify;

class WhenFunctor
{
public:
	WhenFunctor() {}

	template <typename R, typename... arglist>
	FirstProcedureStubbingProgress<R, arglist...>& operator()(const FirstProcedureStubbingProgress<R, arglist...>& stubbingProgress) {
		return  (FirstProcedureStubbingProgress<R, arglist...>&)stubbingProgress;
	}

	template <typename R, typename... arglist>
	FirstFunctionStubbingProgress<R, arglist...>& operator()(const FirstFunctionStubbingProgress<R, arglist...>& stubbingProgress) {
		return  (FirstFunctionStubbingProgress<R, arglist...>&)stubbingProgress;
	}

} static When;

class StubFunctor
{
private:
	void operator() (){}
public:
	StubFunctor() {}

	template <typename H>
	H& operator() (H& head) {
		//When(head).startStubbing();
		head.startStubbing();
		return head;
	}

	template <typename H, typename... M>
	void operator() (H& head, M&... tail) {
		//When(head).startStubbing();
{'fraction_non_alphanumeric': 0.1777111777111777, 'fraction_numerical': 0.000555000555000555, 'mean_word_length': 5.986816595579682, 'pattern_counts': {'":': 0, '<': 265, '<?xml version=': 0, '>': 265, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2468846', 'n_tokens_mistral': 6299, 'n_tokens_neox': 6050, 'n_words': 1105}