c++之sigslot库

这篇博客介绍了在Windows 10环境下,使用VS2017进行C++开发时,如何解决使用sigslot库编译出错的问题,并提供了修正后的sigslot.h文件代码。
摘要由CSDN通过智能技术生成

关于

本文演示环境: win10 + VS2017

1. demo

#include <iostream>
#include "sigslot.h"

using namespace sigslot;

class Switch
{
public:
	signal0<>  clicked;
};

class Light : public has_slots<>
{
public:
	void on()
	{
		std::cout << "the light is on\n";
	}
};


int main(int argc, char *argv[])
{
	Light light;
	Switch sw;
	sw.clicked.connect(&light, &Light::on);

	sw.clicked.emit();


	system("pause");

	return 0;
}

2.编译出错

下载原版sigslot.h文件编译出错:

1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(419): warning C4346: “const_iterator”: 依赖名称不是类型
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(419): note: 用“typename”为前缀来表示类型
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(476): note: 参见对正在编译的 类 模板 实例化 "sigslot::has_slots<mt_policy>" 的引用
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(419): error C2061: 语法错误: 标识符“const_iterator”
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(419): error C2238: 意外的标记位于“;”之前
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(431): error C2760: 语法错误: 意外的令牌“标识符”,预期的令牌为“;”
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(462): error C2760: 语法错误: 意外的令牌“标识符”,预期的令牌为“;”
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(493): error C2760: 语法错误: 意外的令牌“标识符”,预期的令牌为“;”
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(587): note: 参见对正在编译的 类 模板 实例化 "sigslot::_signal_base0<mt_policy>" 的引用
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(493): error C7510: “const_iterator”: 类型 从属名称的使用必须以“typename”为前缀
1>c:\users\xxxxxx\desktop\demo_sigslot\sigslot.h(513): error C2760: 语法错误: 意外的令牌“标识符”,预期的令牌为“;”
.......

3.正确编译

替换下面的代码 到 sigslog.h中,编译成功,编译及运行结果:

4. sigslot.h

修改后的sigslot.h说明如下:

// Libjingle specific:
// This file has been modified such that has_slots and signalx do not have to be
// using the same threading requirements. E.g. it is possible to connect a
// has_slots<single_threaded> and signal0<multi_threaded_local> or
// has_slots<multi_threaded_local> and signal0<single_threaded>.
// If has_slots is single threaded the user must ensure that it is not trying
// to connect or disconnect to signalx concurrently or data race may occur.
// If signalx is single threaded the user must ensure that disconnect, connect
// or signal is not happening concurrently or data race may occur.

文件源码:

// sigslot.h: Signal/Slot classes
//
// Written by Sarah Thompson (sarah@telergy.com) 2002.
//
// License: Public domain. You are free to use this code however you like, with the proviso that
//          the author takes on no responsibility or liability for any use.
//
// QUICK DOCUMENTATION
//
//              (see also the full documentation at http://sigslot.sourceforge.net/)
//
//      #define switches
//          SIGSLOT_PURE_ISO            - Define this to force ISO C++ compliance. This also disables
//                                        all of the thread safety support on platforms where it is
//                                        available.
//
//          SIGSLOT_USE_POSIX_THREADS   - Force use of Posix threads when using a C++ compiler other than
//                                        gcc on a platform that supports Posix threads. (When using gcc,
//                                        this is the default - use SIGSLOT_PURE_ISO to disable this if
//                                        necessary)
//
//          SIGSLOT_DEFAULT_MT_POLICY   - Where thread support is enabled, this defaults to multi_threaded_global.
//                                        Otherwise, the default is single_threaded. #define this yourself to
//                                        override the default. In pure ISO mode, anything other than
//                                        single_threaded will cause a compiler error.
//
//      PLATFORM NOTES
//
//          Win32                       - On Win32, the WIN32 symbol must be #defined. Most mainstream
//                                        compilers do this by default, but you may need to define it
//                                        yourself if your build environment is less standard. This causes
//                                        the Win32 thread support to be compiled in and used automatically.
//
//          Unix/Linux/BSD, etc.        - If you're using gcc, it is assumed that you have Posix threads
//                                        available, so they are used automatically. You can override this
//                                        (as under Windows) with the SIGSLOT_PURE_ISO switch. If you're using
//                                        something other than gcc but still want to use Posix threads, you
//                                        need to #define SIGSLOT_USE_POSIX_THREADS.
//
//          ISO C++                     - If none of the supported platforms are detected, or if
//                                        SIGSLOT_PURE_ISO is defined, all multithreading support is turned off,
//                                        along with any code that might cause a pure ISO C++ environment to
//                                        complain. Before you ask, gcc -ansi -pedantic won't compile this
//                                        library, but gcc -ansi is fine. Pedantic mode seems to throw a lot of
//                                        errors that aren't really there. If you feel like investigating this,
//                                        please contact the author.
//
//
//      THREADING MODES
//
//          single_threaded             - Your program is assumed to be single threaded from the point of view
//                                        of signal/slot usage (i.e. all objects using signals and slots are
//                                        created and destroyed from a single thread). Behaviour if objects are
//                                        destroyed concurrently is undefined (i.e. you'll get the occasional
//                                        segmentation fault/memory exception).
//
//          multi_threaded_global       - Your program is assumed to be multi threaded. Objects using signals and
//                                        slots can be safely created and destroyed from any thread, even when
//                                        connections exist. In multi_threaded_global mode, this is achieved by a
//                                        single global mutex (actually a critical section on Windows because they
//                                        are faster). This option uses less OS resources, but results in more
//                                        opportunities for contention, possibly resulting in more context switches
//                                        than are strictly necessary.
//
//          multi_threaded_local        - Behaviour in this mode is essentially the same as multi_threaded_global,
//                                        except that each signal, and each object that inherits has_slots, all
//                                        have their own mutex/critical section. In practice, this means that
//                                        mutex collisions (and hence context switches) only happen if they are
//                                        absolutely essential. However, on some platforms, creating a lot of
//                                        mutexes can slow down the whole OS, so use this option with care.
//
//      USING THE LIBRARY
//
//          See the full documentation at http://sigslot.sourceforge.net/
//
//
// Libjingle specific:
// This file has been modified such that has_slots and signalx do not have to be
// using the same threading requirements. E.g. it is possible to connect a
// has_slots<single_threaded> and signal0<multi_threaded_local> or
// has_slots<multi_threaded_local> and signal0<single_threaded>.
// If has_slots is single threaded the user must ensure that it is not trying
// to connect or disconnect to signalx concurrently or data race may occur.
// If signalx is single threaded the user must ensure that disconnect, connect
// or signal is not happening concurrently or data race may occur.

#ifndef _SIGSLOT_H__
#define _SIGSLOT_H__

#include <list>
#include <set>
#include <stdlib.h>

// On our copy of sigslot.h, we set single threading as default.
#define SIGSLOT_DEFAULT_MT_POLICY single_threaded

#if defined(SIGSLOT_PURE_ISO) || (!defined(WIN32) && !defined(__GNUG__) && !defined(SIGSLOT_USE_POSIX_THREADS))
#   define _SIGSLOT_SINGLE_THREADED
#elif defined(WIN32)
#   define _SIGSLOT_HAS_WIN32_THREADS
#   if !defined(WIN32_LEAN_AND_MEAN)
#       define WIN32_LEAN_AND_MEAN
#   endif
#   include <windows.h>
#elif defined(__GNUG__) || defined(SIGSLOT_USE_POSIX_THREADS)
#   define _SIGSLOT_HAS_POSIX_THREADS
#   include <pthread.h>
#else
#   define _SIGSLOT_SINGLE_THREADED
#endif

#ifndef SIGSLOT_DEFAULT_MT_POLICY
#   ifdef _SIGSLOT_SINGLE_THREADED
#       define SIGSLOT_DEFAULT_MT_POLICY single_threaded
#   else
#       define SIGSLOT_DEFAULT_MT_POLICY multi_threaded_local
#   endif
#endif

// TODO: change this namespace to talk_base?
namespace sigslot {

	class single_threaded
	{
	public:
		single_threaded()
		{
			;
		}

		virtual ~single_threaded()
		{
			;
		}

		virtual void lock()
		{
			;
		}

		virtual void unlock()
		{
			;
		}
	};

#ifdef _SIGSLOT_HAS_WIN32_THREADS
	// The multi threading policies only get compiled in if they are enabled.
	class multi_threaded_global
	{
	public:
		multi_threaded_global()
		{
			static bool isinitialised = false;

			if (!isinitialised)
			{
				InitializeCriticalSection(get_critsec());
				isinitialised = true;
			}
		}

		multi_threaded_global(const multi_threaded_global&)
		{
			;
		}

		virtual ~multi_threaded_global()
		{
			;
		}

		virtual void lock()
		{
			EnterCriticalSection(get_critsec());
		}

		virtual void unlock()
		{
			LeaveCriticalSection(get_critsec());
		}

	private:
		CRITICAL_SECTION* get_critsec()
		{
			static CRITICAL_SECTION g_critsec;
			return &g_critsec;
		}
	};

	class multi_threaded_local
	{
	public:
		multi_threaded_local()
		{
			InitializeCriticalSection(&m_critsec);
		}

		multi_threaded_local(const multi_threaded_local&)
		{
			InitializeCriticalSection(&m_critsec);
		}

		virtual ~multi_threaded_local()
		{
			DeleteCriticalSection(&m_critsec);
		}

		virtual void lock()
		{
			EnterCriticalSection(&m_critsec);
		}

		virtual void unlock()
		{
			LeaveCriticalSection(&m_critsec);
		}

	private:
		CRITICAL_SECTION m_critsec;
	};
#endif // _SIGSLOT_HAS_WIN32_THREADS

#ifdef _SIGSLOT_HAS_POSIX_THREADS
	// The multi threading policies only get compiled in if they are enabled.
	class multi_threaded_global
	{
	public:
		multi_threaded_global()
		{
			pthread_mutex_init(get_mutex(), NULL);
		}

		multi_threaded_global(const multi_threaded_global&)
		{
			;
		}

		virtual ~multi_threaded_global()
		{
			;
		}

		virtual void lock()
		{
			pthread_mutex_lock(get_mutex());
		}

		virtual void unlock()
		{
			pthread_mutex_unlock(get_mutex());
		}

	private:
		pthread_mutex_t* get_mutex()
		{
			static pthread_mutex_t g_mutex;
			return &g_mutex;
		}
	};

	class multi_threaded_local
	{
	public:
		multi_threaded_local()
		{
			pthread_mutex_init(&m_mutex, NULL);
		}

		multi_threaded_local(const multi_threaded_local&)
		{
			pthread_mutex_init(&m_mutex, NULL);
		}

		virtual ~multi_threaded_local()
		{
			pthread_mutex_destroy(&m_mutex);
		}

		virtual void lock()
		{
			pthread_mutex_lock(&m_mutex);
		}

		virtual void unlock()
		{
			pthread_mutex_unlock(&m_mutex);
		}

	private:
		pthread_mutex_t m_mutex;
	};
#endif // _SIGSLOT_HAS_POSIX_THREADS

	template<class mt_policy>
	class lock_block
	{
	public:
		mt_policy *m_mutex;

		lock_block(mt_policy *mtx)
			: m_mutex(mtx)
		{
			m_mutex->lock();
		}

		~lock_block()
		{
			m_mutex->unlock();
		}
	};

	class has_slots_interface;

	template<class mt_policy>
	class _connection_base0
	{
	public:
		virtual ~_connection_base0() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit() = 0;
		virtual _connection_base0* clone() = 0;
		virtual _connection_base0* duplicate(has_slots_interface* pnewdest) = 0;
	};

	template<class arg1_type, class mt_policy>
	class _connection_base1
	{
	public:
		virtual ~_connection_base1() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit(arg1_type) = 0;
		virtual _connection_base1<arg1_type, mt_policy>* clone() = 0;
		virtual _connection_base1<arg1_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
	};

	template<class arg1_type, class arg2_type, class mt_policy>
	class _connection_base2
	{
	public:
		virtual ~_connection_base2() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit(arg1_type, arg2_type) = 0;
		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* clone() = 0;
		virtual _connection_base2<arg1_type, arg2_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
	};

	template<class arg1_type, class arg2_type, class arg3_type, class mt_policy>
	class _connection_base3
	{
	public:
		virtual ~_connection_base3() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit(arg1_type, arg2_type, arg3_type) = 0;
		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* clone() = 0;
		virtual _connection_base3<arg1_type, arg2_type, arg3_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
	};

	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type, class mt_policy>
	class _connection_base4
	{
	public:
		virtual ~_connection_base4() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type) = 0;
		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* clone() = 0;
		virtual _connection_base4<arg1_type, arg2_type, arg3_type, arg4_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
	};

	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
		class arg5_type, class mt_policy>
		class _connection_base5
	{
	public:
		virtual ~_connection_base5() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type,
			arg5_type) = 0;
		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
			arg5_type, mt_policy>* clone() = 0;
		virtual _connection_base5<arg1_type, arg2_type, arg3_type, arg4_type,
			arg5_type, mt_policy>* duplicate(has_slots_interface* pnewdest) = 0;
	};

	template<class arg1_type, class arg2_type, class arg3_type, class arg4_type,
		class arg5_type, class arg6_type, class mt_policy>
		class _connection_base6
	{
	public:
		virtual ~_connection_base6() {}
		virtual has_slots_interface* getdest() const = 0;
		virtual void emit(arg1_type, arg2_type, arg3_type, arg4_type, arg5_type,
			arg6_type) = 0;
		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
			arg5_type, arg6_type, mt_policy>* clone() = 0;
		virtual _connection_base6<arg1_type, arg2_type, arg3_type, arg4_type,
			arg5_type, arg6_type, mt_policy>* duplicate(has_slots_interface* pnewdest
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值