diff --git a/.clang-format b/.clang-format new file mode 100644 index 00000000..b1a077af --- /dev/null +++ b/.clang-format @@ -0,0 +1,14 @@ +BasedOnStyle: Mozilla +Standard: Cpp11 +AlignAfterOpenBracket: false +AlignEscapedNewlinesLeft: true +AlwaysBreakAfterDefinitionReturnType: None +BreakBeforeBraces: Allman +BreakConstructorInitializersBeforeComma: false +ColumnLimit: 100 +ConstructorInitializerAllOnOneLineOrOnePerLine: true +ConstructorInitializerIndentWidth: 0 +IndentCaseLabels: false +SortIncludes: false +AlignTrailingComments: false + diff --git a/.github/workflows/autotools-clang.yml b/.github/workflows/autotools-clang.yml new file mode 100644 index 00000000..756baf23 --- /dev/null +++ b/.github/workflows/autotools-clang.yml @@ -0,0 +1,27 @@ +name: "Autotools: clang" + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Build + run: | + # Prevent blocking apt install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install mm-common clang make docbook-xsl --yes + export CC=clang CXX=clang++ + ./autogen.sh --enable-warnings=fatal + make + - name: Test + run: make check + - name: Distcheck + run: | + # distcheck runs configure again so we need to specify CC and CXX again. + export CC=clang CXX=clang++ + make distcheck diff --git a/.github/workflows/autotools-gcc.yml b/.github/workflows/autotools-gcc.yml new file mode 100644 index 00000000..018fdc1a --- /dev/null +++ b/.github/workflows/autotools-gcc.yml @@ -0,0 +1,27 @@ +name: "Autotools: gcc" + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Build + run: | + # Prevent blocking apt install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install mm-common g++ make docbook-xsl --yes + export CXX=g++ + ./autogen.sh --enable-warnings=fatal + make + - name: Test + run: make check + - name: Distcheck + run: | + # distcheck runs configure again so we need to specify CXX again. + export CXX=g++ + make distcheck diff --git a/.github/workflows/clang-format-check.yml b/.github/workflows/clang-format-check.yml new file mode 100644 index 00000000..ffe78737 --- /dev/null +++ b/.github/workflows/clang-format-check.yml @@ -0,0 +1,19 @@ +name: "Check Code Formatting" + +# Triggered manually +on: [workflow_dispatch] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Check Code Formatting + run: | + # Prevent blocking the install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install clang-format --yes + clang-format --dry-run --Werror `find . -name "*.h" -or -name "*.cc"` diff --git a/.github/workflows/cmake-msvc.yml b/.github/workflows/cmake-msvc.yml new file mode 100644 index 00000000..88a93323 --- /dev/null +++ b/.github/workflows/cmake-msvc.yml @@ -0,0 +1,19 @@ +name: "CMake: MSVC" + +# Triggered manually +on: [workflow_dispatch] + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v1 + - uses: microsoft/setup-msbuild@v1 + - name: Build + run: | + cmake . + msbuild ALL_BUILD.vcxproj + - name: Test + run: msbuild RUN_TESTS.vcxproj diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml new file mode 100644 index 00000000..470b5b76 --- /dev/null +++ b/.github/workflows/cmake.yml @@ -0,0 +1,17 @@ +name: "CMake: gcc" + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Build + run: | + cmake . + make + - name: Test + run: make test diff --git a/.github/workflows/meson-clang.yml b/.github/workflows/meson-clang.yml new file mode 100644 index 00000000..660a7010 --- /dev/null +++ b/.github/workflows/meson-clang.yml @@ -0,0 +1,37 @@ +# 2024-07-19: ubuntu-latest = ubuntu-22.04 +# See https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories +name: "Meson: clang" + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Build + run: | + # Prevent blocking apt install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common clang ninja-build python3-setuptools python3-pip --yes + # Ubuntu 22.04 contains meson 0.61.2, but libsigc++ requires meson >= 0.62.0. + # Install it with pip instead of apt. + sudo pip install "meson>=0.62.0" + export CXX=clang++ + meson setup -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build + cd _build + meson compile + - name: Test + run: | + cd _build + meson test + - name: Dist + run: | + sudo apt install git --yes + # dist runs setup again so we need to specify CXX again. + export CXX=clang++ + cd _build + meson dist diff --git a/.github/workflows/meson-gcc.yml b/.github/workflows/meson-gcc.yml new file mode 100644 index 00000000..fe2ba8ae --- /dev/null +++ b/.github/workflows/meson-gcc.yml @@ -0,0 +1,37 @@ +# 2024-07-19: ubuntu-latest = ubuntu-22.04 +# See https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories +name: "Meson: gcc" + +on: [push] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v1 + - name: Build + run: | + # Prevent blocking apt install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common g++ ninja-build python3-setuptools python3-pip --yes + # Ubuntu 22.04 contains meson 0.61.2, but libsigc++ requires meson >= 0.62.0. + # Install it with pip instead of apt. + sudo pip install "meson>=0.62.0" + export CXX=g++ + meson setup -Dwarnings=fatal -Dwarning_level=3 -Dwerror=true _build + cd _build + meson compile + - name: Test + run: | + cd _build + meson test + - name: Dist + run: | + sudo apt install git --yes + # dist runs setup again so we need to specify CXX again. + export CXX=g++ + cd _build + meson dist diff --git a/.github/workflows/meson-msvc.yml b/.github/workflows/meson-msvc.yml new file mode 100644 index 00000000..a9aef1a1 --- /dev/null +++ b/.github/workflows/meson-msvc.yml @@ -0,0 +1,35 @@ +name: "Meson: MSVC" + +on: [push] + +jobs: + build: + + runs-on: windows-latest + + steps: + - uses: actions/checkout@v3 + - uses: ssciwr/doxygen-install@v1 + - uses: actions/setup-python@v4 + with: + python-version: '3.x' + - run: pip install meson ninja + + - name: Prepare MSVC + uses: bus1/cabuild/action/msdevshell@v1 + with: + architecture: x64 + + - name: Configure + # Don't use warning_level or werror. They are applied also to subprojects. + # With the latest fixes in mm-common and libsigc++ it's possible + # to build the reference documentation, but it's error-prone to build + # the manual. AFAIK there are no easily installable docbook5-xml and + # docbook-xsl packages for Windows. + run: meson setup -Dwarnings=fatal -Dbuild-manual=false -Dmm-common:use-network=true _build + + - name: Compile + run: meson compile -C _build + + - name: Test + run: meson test -C _build diff --git a/.github/workflows/publish-docs.yml b/.github/workflows/publish-docs.yml new file mode 100644 index 00000000..6d450fe4 --- /dev/null +++ b/.github/workflows/publish-docs.yml @@ -0,0 +1,79 @@ +# Sample workflow for building and deploying a Jekyll site to GitHub Pages + +# Copied from https://github.com/libsigcplusplus/libsigcplusplus/actions/new +# and changed. Actions -> New workflow -> Pages -> GitHub Pages Jekyll + +name: Publish docs + +# 2025-02-05: ubuntu-latest = ubuntu-24.04 +# See https://docs.github.com/en/actions/using-github-hosted-runners/about-github-hosted-runners/about-github-hosted-runners#standard-github-hosted-runners-for-public-repositories +on: + # Runs on pushes targeting the default branch + push: + branches: ["master"] + + # Allows you to run this workflow manually from the Actions tab + workflow_dispatch: + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. +# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. +concurrency: + group: "pages" + cancel-in-progress: false + +jobs: + # Build job + build: + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Build + run: | + # Prevent blocking apt install on a question during configuring of tzdata. + export ENV DEBIAN_FRONTEND=noninteractive + sudo apt update + sudo apt install libxml2-utils docbook5-xml docbook-xsl mm-common g++ meson ninja-build python3-setuptools python3-pip --yes + meson setup -Dbuild-documentation=true -Dbuild-examples=false -Dbuild-tests=false _build + meson compile -C _build + - name: Collect Documentation + # Collect all documentation to be published. + run: | + mkdir _publish _publish/_layouts _publish/pix _publish/manual _publish/reference + # Copy files from the git repository. + cp docs/_config.yml docs/*.md docs/style.css _publish + cp docs/_layouts/*.html _publish/_layouts + cp docs/pix/logo.gif _publish/pix + # Move generated documentation. + mv _build/docs/docs/manual/html _publish/manual + mv _build/docs/docs/reference/html _publish/reference + mv _build/docs/docs/reference/*.tag _publish/reference/html + - name: Setup Pages + uses: actions/configure-pages@v5 + - name: Build with Jekyll + uses: actions/jekyll-build-pages@v1 + with: + source: ./_publish + destination: ./_site + - name: Upload artifact + uses: actions/upload-pages-artifact@v3 + + # Deployment job + # Publish documentation at https://libsigcplusplus.github.io/libsigcplusplus/ + deploy: + environment: + name: github-pages + url: ${{ steps.deployment.outputs.page_url }} + runs-on: ubuntu-latest + needs: build + steps: + - name: Deploy to GitHub Pages + id: deployment + uses: actions/deploy-pages@v4 + diff --git a/.gitignore b/.gitignore index 14155c15..c55c4a07 100644 --- a/.gitignore +++ b/.gitignore @@ -7,8 +7,9 @@ Makefile.in *.l[ao] *~ /INSTALL -/MSVC_Net201?/sigc.rc -/MSVC_Net201?/sigc++config.h +/MSVC_NMake/sigc.rc +/MSVC_NMake/sigc++config.h +/build/compile /aclocal.m4 /autom4te.cache/ /config.h @@ -23,3 +24,6 @@ Makefile.in /sigc++config.h /sigc++-*.pc /stamp-h? +untracked/build_scripts/ +untracked/docs/ +*.pro.user diff --git a/AUTHORS b/AUTHORS deleted file mode 100644 index 000671ac..00000000 --- a/AUTHORS +++ /dev/null @@ -1,8 +0,0 @@ -Martin Schulze -Murray Cumming -Cedric Gustin (win32 support) -Timothy M. Shead and James Lin (MSVC support) -Damien Carbery (Sun FORTE C++ support) -Takashi Takekawa (Intel C++ support) -Andreas Rottmann (make system) -Karl Einar Nelson (initial version 1.9.4) diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 00000000..ee64a3a4 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,125 @@ +# Copyright 2016, The libsigc++ Development Team +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . + +cmake_minimum_required (VERSION 3.10) + +set (SIGCXX_MAJOR_VERSION 3) +set (SIGCXX_MINOR_VERSION 4) +set (SIGCXX_MICRO_VERSION 0) + +set (SIGCXX_API_VERSION 3.0) +set (PACKAGE_VERSION ${SIGCXX_MAJOR_VERSION}.${SIGCXX_MINOR_VERSION}.${SIGCXX_MICRO_VERSION}) +set (LIBSIGCPP_SOVERSION 0) +set (MSVC_STATIC_CXXFLAG "") + +option (SIGCXX_DISABLE_DEPRECATED "Disable deprecated" OFF) + +project (sigc++) + +set( CMAKE_CXX_STANDARD 17 ) + +# Turn on warnings for MSVC. Remove the CMake default of /W3 because when you +# add /W4, MSVC will complain about two warning level flags. This default +# changed at CMake 3.15 (see +# https://cmake.org/cmake/help/v3.15/policy/CMP0092.html#policy:CMP0092 for +# more details) + if (MSVC AND CMAKE_VERSION VERSION_LESS "13.15") + string(REGEX REPLACE "(^|[ \t])/W[0-9]($|[ \t])" "\\1\\2" CMAKE_C_FLAGS "${CMAKE_C_FLAGS}") + string(REGEX REPLACE "(^|[ \t])/W[0-9]($|[ \t])" "\\1\\2" CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS}") +endif() + +# Add compiler warning flags & turn warnings into errors +add_compile_options( + "$<$,$>:/W4;/WX>" + "$<$,$>:-pedantic;-Wall;-Wextra;-Wsuggest-override;-Wshadow;-Wzero-as-null-pointer-constant;-Wformat-security>" + "$<$,$,$,$>:-pedantic;-Wall;-Wextra;-Wshadow;-Wzero-as-null-pointer-constant;-Wformat-security>" +) + +set (PROJECT_SOURCE_DIR "${sigc++_SOURCE_DIR}/sigc++") + +include_directories (${sigc++_SOURCE_DIR}) +include_directories (${sigc++_BINARY_DIR}) + +configure_file (sigc++config.h.cmake sigc++config.h) + +set (prefix ${CMAKE_INSTALL_PREFIX}) +set (exec_prefix \${prefix}) +set (libdir \${exec_prefix}/lib) +set (datarootdir \${prefix}) +set (datadir \${datarootdir}) +set (includedir \${prefix}/include) +set (top_srcdir .) +configure_file (sigc++.pc.in sigc++-${SIGCXX_API_VERSION}.pc @ONLY) +configure_file (sigc++-uninstalled.pc.in sigc++-${SIGCXX_API_VERSION}-uninstalled.pc @ONLY) + +if (NOT TARGET uninstall) +configure_file( + "${CMAKE_CURRENT_SOURCE_DIR}/cmake_uninstall.cmake.in" + "${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake" + IMMEDIATE @ONLY) + +add_custom_target(uninstall + COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/cmake_uninstall.cmake) +endif() + +install (FILES + "${CMAKE_CURRENT_BINARY_DIR}/sigc++config.h" + DESTINATION + "${CMAKE_INSTALL_PREFIX}/lib/${PROJECT_NAME}-${SIGCXX_API_VERSION}/include") + +install (FILES + "${CMAKE_CURRENT_BINARY_DIR}/sigc++-${SIGCXX_API_VERSION}.pc" + DESTINATION + "${CMAKE_INSTALL_PREFIX}/lib/pkgconfig") + +enable_testing() + + + +add_subdirectory (sigc++) +add_subdirectory (examples) +add_subdirectory (tests) + + +set (PROJECT_CMAKE_NAME "${PROJECT_NAME}-3") +set (VERSION_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_CMAKE_NAME}ConfigVersion.cmake") +set (LIBSIGCXX_INCLUDE_DIR "${CMAKE_INSTALL_PREFIX}/lib/${PROJECT_NAME}-${SIGCXX_API_VERSION}/include") +set (PROJECT_CONFIG "${CMAKE_CURRENT_BINARY_DIR}/${PROJECT_CMAKE_NAME}Config.cmake") +set (CONFIG_INSTALL_DIR "lib/cmake/${PROJECT_CMAKE_NAME}") +set (TARGETS_EXPORT_NAME "${PROJECT_CMAKE_NAME}Targets") +include (CMakePackageConfigHelpers) + +write_basic_package_version_file ( + "${VERSION_CONFIG}" + VERSION ${PACKAGE_VERSION} + COMPATIBILITY SameMajorVersion +) + +configure_package_config_file ( + "cmake/sigc++-3Config.cmake.in" + "${PROJECT_CONFIG}" + INSTALL_DESTINATION "${CONFIG_INSTALL_DIR}" +) + +install ( + FILES "${PROJECT_CONFIG}" "${VERSION_CONFIG}" + DESTINATION "${CONFIG_INSTALL_DIR}" +) + +install ( + EXPORT "${TARGETS_EXPORT_NAME}" + DESTINATION "${CONFIG_INSTALL_DIR}" +) diff --git a/COPYING b/COPYING index c4792dd2..341c30bd 100644 --- a/COPYING +++ b/COPYING @@ -1,515 +1,166 @@ + GNU LESSER GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 - GNU LESSER GENERAL PUBLIC LICENSE - Version 2.1, February 1999 - - Copyright (C) 1991, 1999 Free Software Foundation, Inc. - 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. -[This is the first released version of the Lesser GPL. It also counts - as the successor of the GNU Library Public License, version 2, hence - the version number 2.1.] - - Preamble - - The licenses for most software are designed to take away your -freedom to share and change it. By contrast, the GNU General Public -Licenses are intended to guarantee your freedom to share and change -free software--to make sure the software is free for all its users. - - This license, the Lesser General Public License, applies to some -specially designated software packages--typically libraries--of the -Free Software Foundation and other authors who decide to use it. You -can use it too, but we suggest you first think carefully about whether -this license or the ordinary General Public License is the better -strategy to use in any particular case, based on the explanations -below. - - When we speak of free software, we are referring to freedom of use, -not price. Our General Public Licenses are designed to make sure that -you have the freedom to distribute copies of free software (and charge -for this service if you wish); that you receive source code or can get -it if you want it; that you can change the software and use pieces of -it in new free programs; and that you are informed that you can do -these things. - - To protect your rights, we need to make restrictions that forbid -distributors to deny you these rights or to ask you to surrender these -rights. These restrictions translate to certain responsibilities for -you if you distribute copies of the library or if you modify it. - - For example, if you distribute copies of the library, whether gratis -or for a fee, you must give the recipients all the rights that we gave -you. You must make sure that they, too, receive or can get the source -code. If you link other code with the library, you must provide -complete object files to the recipients, so that they can relink them -with the library after making changes to the library and recompiling -it. And you must show them these terms so they know their rights. - - We protect your rights with a two-step method: (1) we copyright the -library, and (2) we offer you this license, which gives you legal -permission to copy, distribute and/or modify the library. - - To protect each distributor, we want to make it very clear that -there is no warranty for the free library. Also, if the library is -modified by someone else and passed on, the recipients should know -that what they have is not the original version, so that the original -author's reputation will not be affected by problems that might be -introduced by others. -^L - Finally, software patents pose a constant threat to the existence of -any free program. We wish to make sure that a company cannot -effectively restrict the users of a free program by obtaining a -restrictive license from a patent holder. Therefore, we insist that -any patent license obtained for a version of the library must be -consistent with the full freedom of use specified in this license. - - Most GNU software, including some libraries, is covered by the -ordinary GNU General Public License. This license, the GNU Lesser -General Public License, applies to certain designated libraries, and -is quite different from the ordinary General Public License. We use -this license for certain libraries in order to permit linking those -libraries into non-free programs. - - When a program is linked with a library, whether statically or using -a shared library, the combination of the two is legally speaking a -combined work, a derivative of the original library. The ordinary -General Public License therefore permits such linking only if the -entire combination fits its criteria of freedom. The Lesser General -Public License permits more lax criteria for linking other code with -the library. - - We call this license the "Lesser" General Public License because it -does Less to protect the user's freedom than the ordinary General -Public License. It also provides other free software developers Less -of an advantage over competing non-free programs. These disadvantages -are the reason we use the ordinary General Public License for many -libraries. However, the Lesser license provides advantages in certain -special circumstances. - - For example, on rare occasions, there may be a special need to -encourage the widest possible use of a certain library, so that it -becomes -a de-facto standard. To achieve this, non-free programs must be -allowed to use the library. A more frequent case is that a free -library does the same job as widely used non-free libraries. In this -case, there is little to gain by limiting the free library to free -software only, so we use the Lesser General Public License. - - In other cases, permission to use a particular library in non-free -programs enables a greater number of people to use a large body of -free software. For example, permission to use the GNU C Library in -non-free programs enables many more people to use the whole GNU -operating system, as well as its variant, the GNU/Linux operating -system. - - Although the Lesser General Public License is Less protective of the -users' freedom, it does ensure that the user of a program that is -linked with the Library has the freedom and the wherewithal to run -that program using a modified version of the Library. - - The precise terms and conditions for copying, distribution and -modification follow. Pay close attention to the difference between a -"work based on the library" and a "work that uses the library". The -former contains code derived from the library, whereas the latter must -be combined with the library in order to run. -^L - GNU LESSER GENERAL PUBLIC LICENSE - TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION - - 0. This License Agreement applies to any software library or other -program which contains a notice placed by the copyright holder or -other authorized party saying it may be distributed under the terms of -this Lesser General Public License (also called "this License"). -Each licensee is addressed as "you". - - A "library" means a collection of software functions and/or data -prepared so as to be conveniently linked with application programs -(which use some of those functions and data) to form executables. - - The "Library", below, refers to any such software library or work -which has been distributed under these terms. A "work based on the -Library" means either the Library or any derivative work under -copyright law: that is to say, a work containing the Library or a -portion of it, either verbatim or with modifications and/or translated -straightforwardly into another language. (Hereinafter, translation is -included without limitation in the term "modification".) - - "Source code" for a work means the preferred form of the work for -making modifications to it. For a library, complete source code means -all the source code for all modules it contains, plus any associated -interface definition files, plus the scripts used to control -compilation -and installation of the library. - - Activities other than copying, distribution and modification are not -covered by this License; they are outside its scope. The act of -running a program using the Library is not restricted, and output from -such a program is covered only if its contents constitute a work based -on the Library (independent of the use of the Library in a tool for -writing it). Whether that is true depends on what the Library does -and what the program that uses the Library does. - - 1. You may copy and distribute verbatim copies of the Library's -complete source code as you receive it, in any medium, provided that -you conspicuously and appropriately publish on each copy an -appropriate copyright notice and disclaimer of warranty; keep intact -all the notices that refer to this License and to the absence of any -warranty; and distribute a copy of this License along with the -Library. - You may charge a fee for the physical act of transferring a copy, -and you may at your option offer warranty protection in exchange for a -fee. - - 2. You may modify your copy or copies of the Library or any portion -of it, thus forming a work based on the Library, and copy and -distribute such modifications or work under the terms of Section 1 -above, provided that you also meet all of these conditions: - - a) The modified work must itself be a software library. - - b) You must cause the files modified to carry prominent notices - stating that you changed the files and the date of any change. - - c) You must cause the whole of the work to be licensed at no - charge to all third parties under the terms of this License. - - d) If a facility in the modified Library refers to a function or a - table of data to be supplied by an application program that uses - the facility, other than as an argument passed when the facility - is invoked, then you must make a good faith effort to ensure that, - in the event an application does not supply such function or - table, the facility still operates, and performs whatever part of - its purpose remains meaningful. - - (For example, a function in a library to compute square roots has - a purpose that is entirely well-defined independent of the - application. Therefore, Subsection 2d requires that any - application-supplied function or table used by this function must - be optional: if the application does not supply it, the square - root function must still compute square roots.) - -These requirements apply to the modified work as a whole. If -identifiable sections of that work are not derived from the Library, -and can be reasonably considered independent and separate works in -themselves, then this License, and its terms, do not apply to those -sections when you distribute them as separate works. But when you -distribute the same sections as part of a whole which is a work based -on the Library, the distribution of the whole must be on the terms of -this License, whose permissions for other licensees extend to the -entire whole, and thus to each and every part regardless of who wrote -it. - -Thus, it is not the intent of this section to claim rights or contest -your rights to work written entirely by you; rather, the intent is to -exercise the right to control the distribution of derivative or -collective works based on the Library. - -In addition, mere aggregation of another work not based on the Library -with the Library (or with a work based on the Library) on a volume of -a storage or distribution medium does not bring the other work under -the scope of this License. - - 3. You may opt to apply the terms of the ordinary GNU General Public -License instead of this License to a given copy of the Library. To do -this, you must alter all the notices that refer to this License, so -that they refer to the ordinary GNU General Public License, version 2, -instead of to this License. (If a newer version than version 2 of the -ordinary GNU General Public License has appeared, then you can specify -that version instead if you wish.) Do not make any other change in -these notices. -^L - Once this change is made in a given copy, it is irreversible for -that copy, so the ordinary GNU General Public License applies to all -subsequent copies and derivative works made from that copy. - - This option is useful when you wish to copy part of the code of -the Library into a program that is not a library. - - 4. You may copy and distribute the Library (or a portion or -derivative of it, under Section 2) in object code or executable form -under the terms of Sections 1 and 2 above provided that you accompany -it with the complete corresponding machine-readable source code, which -must be distributed under the terms of Sections 1 and 2 above on a -medium customarily used for software interchange. - - If distribution of object code is made by offering access to copy -from a designated place, then offering equivalent access to copy the -source code from the same place satisfies the requirement to -distribute the source code, even though third parties are not -compelled to copy the source along with the object code. - - 5. A program that contains no derivative of any portion of the -Library, but is designed to work with the Library by being compiled or -linked with it, is called a "work that uses the Library". Such a -work, in isolation, is not a derivative work of the Library, and -therefore falls outside the scope of this License. - - However, linking a "work that uses the Library" with the Library -creates an executable that is a derivative of the Library (because it -contains portions of the Library), rather than a "work that uses the -library". The executable is therefore covered by this License. -Section 6 states terms for distribution of such executables. - - When a "work that uses the Library" uses material from a header file -that is part of the Library, the object code for the work may be a -derivative work of the Library even though the source code is not. -Whether this is true is especially significant if the work can be -linked without the Library, or if the work is itself a library. The -threshold for this to be true is not precisely defined by law. - - If such an object file uses only numerical parameters, data -structure layouts and accessors, and small macros and small inline -functions (ten lines or less in length), then the use of the object -file is unrestricted, regardless of whether it is legally a derivative -work. (Executables containing this object code plus portions of the -Library will still fall under Section 6.) - - Otherwise, if the work is a derivative of the Library, you may -distribute the object code for the work under the terms of Section 6. -Any executables containing that work also fall under Section 6, -whether or not they are linked directly with the Library itself. -^L - 6. As an exception to the Sections above, you may also combine or -link a "work that uses the Library" with the Library to produce a -work containing portions of the Library, and distribute that work -under terms of your choice, provided that the terms permit -modification of the work for the customer's own use and reverse -engineering for debugging such modifications. - - You must give prominent notice with each copy of the work that the -Library is used in it and that the Library and its use are covered by -this License. You must supply a copy of this License. If the work -during execution displays copyright notices, you must include the -copyright notice for the Library among them, as well as a reference -directing the user to the copy of this License. Also, you must do one -of these things: - - a) Accompany the work with the complete corresponding - machine-readable source code for the Library including whatever - changes were used in the work (which must be distributed under - Sections 1 and 2 above); and, if the work is an executable linked - with the Library, with the complete machine-readable "work that - uses the Library", as object code and/or source code, so that the - user can modify the Library and then relink to produce a modified - executable containing the modified Library. (It is understood - that the user who changes the contents of definitions files in the - Library will not necessarily be able to recompile the application - to use the modified definitions.) - - b) Use a suitable shared library mechanism for linking with the - Library. A suitable mechanism is one that (1) uses at run time a - copy of the library already present on the user's computer system, - rather than copying library functions into the executable, and (2) - will operate properly with a modified version of the library, if - the user installs one, as long as the modified version is - interface-compatible with the version that the work was made with. - - c) Accompany the work with a written offer, valid for at - least three years, to give the same user the materials - specified in Subsection 6a, above, for a charge no more - than the cost of performing this distribution. - - d) If distribution of the work is made by offering access to copy - from a designated place, offer equivalent access to copy the above - specified materials from the same place. - - e) Verify that the user has already received a copy of these - materials or that you have already sent this user a copy. - - For an executable, the required form of the "work that uses the -Library" must include any data and utility programs needed for -reproducing the executable from it. However, as a special exception, -the materials to be distributed need not include anything that is -normally distributed (in either source or binary form) with the major -components (compiler, kernel, and so on) of the operating system on -which the executable runs, unless that component itself accompanies -the executable. - - It may happen that this requirement contradicts the license -restrictions of other proprietary libraries that do not normally -accompany the operating system. Such a contradiction means you cannot -use both them and the Library together in an executable that you -distribute. -^L - 7. You may place library facilities that are a work based on the -Library side-by-side in a single library together with other library -facilities not covered by this License, and distribute such a combined -library, provided that the separate distribution of the work based on -the Library and of the other library facilities is otherwise -permitted, and provided that you do these two things: - - a) Accompany the combined library with a copy of the same work - based on the Library, uncombined with any other library - facilities. This must be distributed under the terms of the - Sections above. - - b) Give prominent notice with the combined library of the fact - that part of it is a work based on the Library, and explaining - where to find the accompanying uncombined form of the same work. - - 8. You may not copy, modify, sublicense, link with, or distribute -the Library except as expressly provided under this License. Any -attempt otherwise to copy, modify, sublicense, link with, or -distribute the Library is void, and will automatically terminate your -rights under this License. However, parties who have received copies, -or rights, from you under this License will not have their licenses -terminated so long as such parties remain in full compliance. - - 9. You are not required to accept this License, since you have not -signed it. However, nothing else grants you permission to modify or -distribute the Library or its derivative works. These actions are -prohibited by law if you do not accept this License. Therefore, by -modifying or distributing the Library (or any work based on the -Library), you indicate your acceptance of this License to do so, and -all its terms and conditions for copying, distributing or modifying -the Library or works based on it. - - 10. Each time you redistribute the Library (or any work based on the -Library), the recipient automatically receives a license from the -original licensor to copy, distribute, link with or modify the Library -subject to these terms and conditions. You may not impose any further -restrictions on the recipients' exercise of the rights granted herein. -You are not responsible for enforcing compliance by third parties with -this License. -^L - 11. If, as a consequence of a court judgment or allegation of patent -infringement or for any other reason (not limited to patent issues), -conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot -distribute so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you -may not distribute the Library at all. For example, if a patent -license would not permit royalty-free redistribution of the Library by -all those who receive copies directly or indirectly through you, then -the only way you could satisfy both it and this License would be to -refrain entirely from distribution of the Library. - -If any portion of this section is held invalid or unenforceable under -any particular circumstance, the balance of the section is intended to -apply, and the section as a whole is intended to apply in other -circumstances. - -It is not the purpose of this section to induce you to infringe any -patents or other property right claims or to contest validity of any -such claims; this section has the sole purpose of protecting the -integrity of the free software distribution system which is -implemented by public license practices. Many people have made -generous contributions to the wide range of software distributed -through that system in reliance on consistent application of that -system; it is up to the author/donor to decide if he or she is willing -to distribute software through any other system and a licensee cannot -impose that choice. - -This section is intended to make thoroughly clear what is believed to -be a consequence of the rest of this License. - - 12. If the distribution and/or use of the Library is restricted in -certain countries either by patents or by copyrighted interfaces, the -original copyright holder who places the Library under this License -may add an explicit geographical distribution limitation excluding those -countries, so that distribution is permitted only in or among -countries not thus excluded. In such case, this License incorporates -the limitation as if written in the body of this License. - - 13. The Free Software Foundation may publish revised and/or new -versions of the Lesser General Public License from time to time. -Such new versions will be similar in spirit to the present version, -but may differ in detail to address new problems or concerns. - -Each version is given a distinguishing version number. If the Library -specifies a version number of this License which applies to it and -"any later version", you have the option of following the terms and -conditions either of that version or of any later version published by -the Free Software Foundation. If the Library does not specify a -license version number, you may choose any version ever published by -the Free Software Foundation. -^L - 14. If you wish to incorporate parts of the Library into other free -programs whose distribution conditions are incompatible with these, -write to the author to ask for permission. For software which is -copyrighted by the Free Software Foundation, write to the Free -Software Foundation; we sometimes make exceptions for this. Our -decision will be guided by the two goals of preserving the free status -of all derivatives of our free software and of promoting the sharing -and reuse of software generally. - - NO WARRANTY - - 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO -WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW. -EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR -OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY -KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE -LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME -THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN -WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY -AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU -FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR -CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE -LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING -RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A -FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF -SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH -DAMAGES. - - END OF TERMS AND CONDITIONS -^L - How to Apply These Terms to Your New Libraries - - If you develop a new library, and you want it to be of the greatest -possible use to the public, we recommend making it free software that -everyone can redistribute and change. You can do so by permitting -redistribution under these terms (or, alternatively, under the terms -of the ordinary General Public License). - - To apply these terms, attach the following notices to the library. -It is safest to attach them to the start of each source file to most -effectively convey the exclusion of warranty; and each file should -have at least the "copyright" line and a pointer to where the full -notice is found. - - - - Copyright (C) - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - -Also add information on how to contact you by electronic and paper -mail. - -You should also get your employer (if you work as a programmer) or -your -school, if any, to sign a "copyright disclaimer" for the library, if -necessary. Here is a sample; alter the names: - - Yoyodyne, Inc., hereby disclaims all copyright interest in the - library `Frob' (a library for tweaking knobs) written by James -Random Hacker. - - , 1 April 1990 - Ty Coon, President of Vice - -That's all there is to it! + This version of the GNU Lesser General Public License incorporates +the terms and conditions of version 3 of the GNU General Public +License, supplemented by the additional permissions listed below. + + 0. Additional Definitions. + As used herein, "this License" refers to version 3 of the GNU Lesser +General Public License, and the "GNU GPL" refers to version 3 of the GNU +General Public License. + + "The Library" refers to a covered work governed by this License, +other than an Application or a Combined Work as defined below. + + An "Application" is any work that makes use of an interface provided +by the Library, but which is not otherwise based on the Library. +Defining a subclass of a class defined by the Library is deemed a mode +of using an interface provided by the Library. + + A "Combined Work" is a work produced by combining or linking an +Application with the Library. The particular version of the Library +with which the Combined Work was made is also called the "Linked +Version". + + The "Minimal Corresponding Source" for a Combined Work means the +Corresponding Source for the Combined Work, excluding any source code +for portions of the Combined Work that, considered in isolation, are +based on the Application, and not on the Linked Version. + + The "Corresponding Application Code" for a Combined Work means the +object code and/or source code for the Application, including any data +and utility programs needed for reproducing the Combined Work from the +Application, but excluding the System Libraries of the Combined Work. + + 1. Exception to Section 3 of the GNU GPL. + + You may convey a covered work under sections 3 and 4 of this License +without being bound by section 3 of the GNU GPL. + + 2. Conveying Modified Versions. + + If you modify a copy of the Library, and, in your modifications, a +facility refers to a function or data to be supplied by an Application +that uses the facility (other than as an argument passed when the +facility is invoked), then you may convey a copy of the modified +version: + + a) under this License, provided that you make a good faith effort to + ensure that, in the event an Application does not supply the + function or data, the facility still operates, and performs + whatever part of its purpose remains meaningful, or + + b) under the GNU GPL, with none of the additional permissions of + this License applicable to that copy. + + 3. Object Code Incorporating Material from Library Header Files. + + The object code form of an Application may incorporate material from +a header file that is part of the Library. You may convey such object +code under terms of your choice, provided that, if the incorporated +material is not limited to numerical parameters, data structure +layouts and accessors, or small macros, inline functions and templates +(ten or fewer lines in length), you do both of the following: + + a) Give prominent notice with each copy of the object code that the + Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the object code with a copy of the GNU GPL and this license + document. + + 4. Combined Works. + + You may convey a Combined Work under terms of your choice that, +taken together, effectively do not restrict modification of the +portions of the Library contained in the Combined Work and reverse +engineering for debugging such modifications, if you also do each of +the following: + + a) Give prominent notice with each copy of the Combined Work that + the Library is used in it and that the Library and its use are + covered by this License. + + b) Accompany the Combined Work with a copy of the GNU GPL and this license + document. + + c) For a Combined Work that displays copyright notices during + execution, include the copyright notice for the Library among + these notices, as well as a reference directing the user to the + copies of the GNU GPL and this license document. + + d) Do one of the following: + + 0) Convey the Minimal Corresponding Source under the terms of this + License, and the Corresponding Application Code in a form + suitable for, and under terms that permit, the user to + recombine or relink the Application with a modified version of + the Linked Version to produce a modified Combined Work, in the + manner specified by section 6 of the GNU GPL for conveying + Corresponding Source. + + 1) Use a suitable shared library mechanism for linking with the + Library. A suitable mechanism is one that (a) uses at run time + a copy of the Library already present on the user's computer + system, and (b) will operate properly with a modified version + of the Library that is interface-compatible with the Linked + Version. + + e) Provide Installation Information, but only if you would otherwise + be required to provide such information under section 6 of the + GNU GPL, and only to the extent that such information is + necessary to install and execute a modified version of the + Combined Work produced by recombining or relinking the + Application with a modified version of the Linked Version. (If + you use option 4d0, the Installation Information must accompany + the Minimal Corresponding Source and Corresponding Application + Code. If you use option 4d1, you must provide the Installation + Information in the manner specified by section 6 of the GNU GPL + for conveying Corresponding Source.) + + 5. Combined Libraries. + + You may place library facilities that are a work based on the +Library side by side in a single library together with other library +facilities that are not Applications and are not covered by this +License, and convey such a combined library under terms of your +choice, if you do both of the following: + + a) Accompany the combined library with a copy of the same work based + on the Library, uncombined with any other library facilities, + conveyed under the terms of this License. + + b) Give prominent notice with the combined library that part of it + is a work based on the Library, and explaining where to find the + accompanying uncombined form of the same work. + + 6. Revised Versions of the GNU Lesser General Public License. + + The Free Software Foundation may publish revised and/or new versions +of the GNU Lesser General Public License from time to time. Such new +versions will be similar in spirit to the present version, but may +differ in detail to address new problems or concerns. + + Each version is given a distinguishing version number. If the +Library as you received it specifies that a certain numbered version +of the GNU Lesser General Public License "or any later version" +applies to it, you have the option of following the terms and +conditions either of that published version or of any later version +published by the Free Software Foundation. If the Library as you +received it does not specify a version number of the GNU Lesser +General Public License, you may choose any version of the GNU Lesser +General Public License ever published by the Free Software Foundation. + + If the Library as you received it specifies that a proxy can decide +whether future versions of the GNU Lesser General Public License shall +apply, that proxy's public statement of acceptance of any version is +permanent authorization for you to choose that version for the +Library. diff --git a/ChangeLog.pre-2-3-1 b/ChangeLog.pre-2-3-1 deleted file mode 100644 index 5cdd5f48..00000000 --- a/ChangeLog.pre-2-3-1 +++ /dev/null @@ -1,2759 +0,0 @@ -2.3.1: - -2012-10-18 Murray Cumming - - Update the Doxyfile.in syntax. - - * docs/reference/Doxyfile.in: By running doxygen -u - on it. - -2012-10-17 Kjell Ahlstedt - - Add some missing newin{}. - - * docs/reference/Doxyfile.in: Add ALIASES newin. - * sigc++/functors/macros/functor_trait.h.m4: Add newin{2,2,11} to - SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE. - * sigc++/signal_base.h: Add newin{2,4} to signal_impl::blocked(), block() and - signal_base::blocked(), block(), unblock(). Bug #153780. - -2012-10-12 Kjell Ahlstedt - - signal_base: Add blocked(), block(), unblock(). - - * sigc++/signal_base.[h|cc]: Add signal_impl::blocked(), block() and - signal_base::blocked(), block(), unblock(). Bug #153780. - -2.2.11: - -2012-09-20 Andris Pavenis - - Fix comma operator in lambda expressions. - - * sigc++/adaptors/lambda/macros/operator.h.m4: Add lambda_action<> - specialization for comma operator (operator,()). - * tests/test_cpp11_lambda.cc: - * tests/test_lambda.cc: Add a test case for the comma operator. Bug #342911. - -2012-09-19 Kjell Ahlstedt - - Add SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE. - - * sigc++/adaptors/lambda/macros/base.h.m4: - * sigc++/adaptors/lambda/macros/group.h.m4: - * sigc++/functors/macros/functor_trait.h.m4: - * tests/test_cpp11_lambda.cc: Replace the preprocessor macro - SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH(C_keyword) with - SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE. Bug #672555. - -2012-09-10 Kjell Ahlstedt - - Use std::size_t and std::ptrdiff_t. - - * sigc++/macros/signal.h.m4: Use std::size_t and std::ptrdiff_t instead - of ::size_t and ::ptrdiff_t. Only the std versions are required to be - declared in . - * sigc++/signal_base.h: Use std::size_t instead of ::size_t. (I did not change - MSVC++-only code in this file and other files.) - -2012-09-07 Kjell Ahlstedt - - Fix 'make check' with gcc 4.7. - - * sigc++/adaptors/lambda/macros/base.h.m4: Define sigc::unwrap_lambda_value() - before it's used in sigc::lambda::operator[]() and operator=(). - * sigc++/adaptors/lambda/macros/group.h.m4: Fix the C++11 examples in the - documentation as in test_cpp11_lambda.cc. - * tests/test_cpp11_lambda.cc: Only variables with automatic storage duration - shall be captured in C++11 lambda expressions. - -2012-08-28 Kjell Ahlstedt - - Update .gitignore and tests/.gitignore - - * .gitignore: Add *~ (gedit's backup files). - * tests/.gitignore: Add missing executable test files. - -2012-08-28 Kjell Ahlstedt - - Add SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH for C++11 lambda expressions. - - * sigc++/functors/macros/functor_trait.h.m4: Add the preprocessor macro - SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH(C_keyword), which makes it possible to - assign C++11 lambda expressions with any return type to slots. - Thanks to Chow Loong Jin, who posted similar code on libsigc-list. - * sigc++/adaptors/lambda/macros/base.h.m4: - * sigc++/adaptors/lambda/macros/group.h.m4: Add information on C++11 lambda - expressions to the documentation of lambda expressions and sigc::group(). - * tests/Makefile.am: Add test_cpp11_lambda.cc. - * tests/test_cpp11_lambda.cc: New test case, showing that most uses of - libsigc++'s lambda expressions can be replaced by standard C++11 lambda - expressions. Bug #672555. - -2012-03-19 Kjell Ahlstedt - - Enable test_lambda in 'make check'. - - * tests/Makefile.am: Enable test_lambda in 'make check'. - * tests/test_lambda.cc: Comment out the tests with sigc::ref() in lambda - functions' parameter lists. See Bug #669128. - -2.2.10: - -2011-07-21 Thomas Rydzynski - - Mention visit_each() in the documentation of sigc::adapts. - - * sigc++/adaptors/macros/adaptor_trait.h.m4: Mention that a user-supplied - adaptor must be accompanied by a specialization of template function - visit_each(). Correct some minor errors in the example of a user-supplied - adaptor. Bug #486373. - -2011-07-19 Kjell Ahlstedt - - Add a test case for the previous commit. - - * tests/Makefile.am: - * tests/test_bind_refptr.cc: A version of this test is also in glibmm. - Note that this includes a copy/paste of RefPtr. - See Bug #564005#14 (Alexander Shaduri) - -2011-07-14 Kjell Ahlstedt - - slot_rep: Avoid access to deleted object in notify(). - - * sigc++/functors/slot_base.cc: slot_rep::notify() calls disconnect() before - destroy(). If disconnect() has deleted the slot_rep object, destroy() is not - called. Bug #564005. - -2.2.9: - -2011-02-22 Kjell Ahlstedt - - trackable: Avoid calling the same callback function twice - - * sigc++/trackable.cc: Invalidate a callback function entry in - trackable_callback_list::remove_callback() when the list is being cleared. - Bug 589202. - -2011-02-04 Kalev Lember - - Fix the build with GCC 4.6 - - * sigc++/signal_base.h: Include for size_t. - -2010-10-12 David King - - Documentation changes - - * *.h.m4: Minor changes to documentation to fix up code example - formatting, by removing the additional two spaces of indentation. - Additionally, fix some spelling and grammar mistakes and typos. - -2010-09-27 Armin Burgmeier - - * MSVC_Net2005/libsigc++2.sln: - * MSVC_Net2005/libsigc++2.vcproj: - * MSVC_Net2005/tests/test_accumulated/test_accumulated.vcproj: - * MSVC_Net2005/tests/test_bind/test_bind.vcproj: - * MSVC_Net2005/tests/test_bind_return/test_bind_return.vcproj: - * MSVC_Net2005/tests/test_compose/test_compose.vcproj: - * MSVC_Net2005/tests/test_deduce_result_type/test_deduce_result_type.vcproj: - * MSVC_Net2005/tests/test_disconnect/test_disconnect.vcproj: - * MSVC_Net2005/tests/test_disconnect_during_emit/test_disconnect_during_emit.vcproj: - * MSVC_Net2005/tests/test_exception_catch/test_exception_catch.vcproj: - * MSVC_Net2005/tests/test_functor_trait/test_functor_trait.vcproj: - * MSVC_Net2005/tests/test_hide/test_hide.vcproj: - * MSVC_Net2005/tests/test_mem_fun/test_mem_fun.vcproj: - * MSVC_Net2005/tests/test_ptr_fun/test_ptr_fun.vcproj: - * MSVC_Net2005/tests/test_retype/test_retype.vcproj: - * MSVC_Net2005/tests/test_retype_return/test_retype_return.vcproj: - * MSVC_Net2005/tests/test_signal/test_signal.vcproj: - * MSVC_Net2005/tests/test_size/test_size.vcproj: - * MSVC_Net2005/tests/test_slot/test_slot.vcproj: - * MSVC_Net2005/tests/test_trackable/test_trackable.vcproj: - * MSVC_Net2008/libsigc++2.sln: - * MSVC_Net2008/libsigc++2.vcproj: - * MSVC_Net2008/tests/test_accumulated/test_accumulated.vcproj: - * MSVC_Net2008/tests/test_bind/test_bind.vcproj: - * MSVC_Net2008/tests/test_bind_return/test_bind_return.vcproj: - * MSVC_Net2008/tests/test_compose/test_compose.vcproj: - * MSVC_Net2008/tests/test_deduce_result_type/test_deduce_result_type.vcproj: - * MSVC_Net2008/tests/test_disconnect/test_disconnect.vcproj: - * MSVC_Net2008/tests/test_disconnect_during_emit/test_disconnect_during_emit.vcproj: - * MSVC_Net2008/tests/test_exception_catch/test_exception_catch.vcproj: - * MSVC_Net2008/tests/test_functor_trait/test_functor_trait.vcproj: - * MSVC_Net2008/tests/test_hide/test_hide.vcproj: - * MSVC_Net2008/tests/test_mem_fun/test_mem_fun.vcproj: - * MSVC_Net2008/tests/test_ptr_fun/test_ptr_fun.vcproj: - * MSVC_Net2008/tests/test_retype/test_retype.vcproj: - * MSVC_Net2008/tests/test_retype_return/test_retype_return.vcproj: - * MSVC_Net2008/tests/test_signal/test_signal.vcproj: - * MSVC_Net2008/tests/test_size/test_size.vcproj: - * MSVC_Net2008/tests/test_slot/test_slot.vcproj: - * MSVC_Net2008/tests/test_trackable/test_trackable.vcproj: - * MSVC_Net2010/libsigc++2.vcxproj: - * MSVC_Net2010/tests/test_accumulated/test_accumulated.vcxproj: - * MSVC_Net2010/tests/test_bind/test_bind.vcxproj: - * MSVC_Net2010/tests/test_bind_return/test_bind_return.vcxproj: - * MSVC_Net2010/tests/test_compose/test_compose.vcxproj: - * MSVC_Net2010/tests/test_deduce_result_type/test_deduce_result_type.vcxproj: - * MSVC_Net2010/tests/test_disconnect/test_disconnect.vcxproj: - * MSVC_Net2010/tests/test_disconnect_during_emit/test_disconnect_during_emit.vcxproj: - * MSVC_Net2010/tests/test_exception_catch/test_exception_catch.vcxproj: - * MSVC_Net2010/tests/test_functor_trait/test_functor_trait.vcxproj: - * MSVC_Net2010/tests/test_hide/test_hide.vcxproj: - * MSVC_Net2010/tests/test_mem_fun/test_mem_fun.vcxproj: - * MSVC_Net2010/tests/test_ptr_fun/test_ptr_fun.vcxproj: - * MSVC_Net2010/tests/test_retype/test_retype.vcxproj: - * MSVC_Net2010/tests/test_retype_return/test_retype_return.vcxproj: - * MSVC_Net2010/tests/test_signal/test_signal.vcxproj: - * MSVC_Net2010/tests/test_size/test_size.vcxproj: - * MSVC_Net2010/tests/test_slot/test_slot.vcxproj: - * MSVC_Net2010/tests/test_trackable/test_trackable.vcxproj: Add 64 - bit support to MSVC project files. - -2010-09-27 Armin Burgmeier - - * MSVC_Net2005/libsigc++2.sln: - * MSVC_Net2005/tests/test_accumulated/test_accumulated.vcproj: - * MSVC_Net2008/libsigc++2.sln: - * MSVC_Net2008/tests/test_accumulated/test_accumulated.vcproj: Add - test_accumulated to the MSVC projects. - -2010-09-19 Armin Burgmeier - - * MSVC_Net2010/filelist.am: - * MSVC_Net2010/libsigc++2.sln: - * MSVC_Net2010/libsigc++2.vcxproj: - * MSVC_Net2010/libsigc++2.vcxproj.filters: - * MSVC_Net2010/sigc.rc.in: - * MSVC_Net2010/tests/test_accumulated/test_accumulated.vcxproj: - * MSVC_Net2010/tests/test_accumulated/test_accumulated.vcxproj.filters: - * MSVC_Net2010/tests/test_bind/test_bind.vcxproj: - * MSVC_Net2010/tests/test_bind/test_bind.vcxproj.filters: - * MSVC_Net2010/tests/test_bind_return/test_bind_return.vcxproj: - * MSVC_Net2010/tests/test_bind_return/test_bind_return.vcxproj.filters: - * MSVC_Net2010/tests/test_compose/test_compose.vcxproj: - * MSVC_Net2010/tests/test_compose/test_compose.vcxproj.filters: - * MSVC_Net2010/tests/test_deduce_result_type/test_deduce_result_type.vcxproj: - * MSVC_Net2010/tests/test_deduce_result_type/test_deduce_result_type.vcxproj.filters: - * MSVC_Net2010/tests/test_disconnect/test_disconnect.vcxproj: - * MSVC_Net2010/tests/test_disconnect/test_disconnect.vcxproj.filters: - * MSVC_Net2010/tests/test_disconnect_during_emit/test_disconnect_during_emit.vcxproj: - * MSVC_Net2010/tests/test_disconnect_during_emit/test_disconnect_during_emit.vcxproj.filters: - * MSVC_Net2010/tests/test_exception_catch/test_exception_catch.vcxproj: - * MSVC_Net2010/tests/test_exception_catch/test_exception_catch.vcxproj.filters: - * MSVC_Net2010/tests/test_functor_trait/test_functor_trait.vcxproj: - * MSVC_Net2010/tests/test_functor_trait/test_functor_trait.vcxproj.filters: - * MSVC_Net2010/tests/test_hide/test_hide.vcxproj: - * MSVC_Net2010/tests/test_hide/test_hide.vcxproj.filters: - * MSVC_Net2010/tests/test_mem_fun/test_mem_fun.vcxproj: - * MSVC_Net2010/tests/test_mem_fun/test_mem_fun.vcxproj.filters: - * MSVC_Net2010/tests/test_ptr_fun/test_ptr_fun.vcxproj: - * MSVC_Net2010/tests/test_ptr_fun/test_ptr_fun.vcxproj.filters: - * MSVC_Net2010/tests/test_retype/test_retype.vcxproj: - * MSVC_Net2010/tests/test_retype/test_retype.vcxproj.filters: - * MSVC_Net2010/tests/test_retype_return/test_retype_return.vcxproj: - * MSVC_Net2010/tests/test_retype_return/test_retype_return.vcxproj.filters: - * MSVC_Net2010/tests/test_signal/test_signal.vcxproj: - * MSVC_Net2010/tests/test_signal/test_signal.vcxproj.filters: - * MSVC_Net2010/tests/test_size/test_size.vcxproj: - * MSVC_Net2010/tests/test_size/test_size.vcxproj.filters: - * MSVC_Net2010/tests/test_slot/test_slot.vcxproj: - * MSVC_Net2010/tests/test_slot/test_slot.vcxproj.filters: - * MSVC_Net2010/tests/test_trackable/test_trackable.vcxproj: - * MSVC_Net2010/tests/test_trackable/test_trackable.vcxproj.filters: - - * Makefile.am: - * configure.ac: Added project files for Visual Studio 2010. - -2010-06-05 David King - - Small website updates - - * docs/index.html: Remove broken namespace links. - * docs/website/doc.shtml: Link to library.gnome.org tutorial and API - reference. - -2.2.8: - -2010-06-04 Murray Cumming - - Manual: Add an id="index" attribute in case that helps library.gnome.org. - - * docs/manual/libsigc_manual.xml: Add it to the tag. - -2.2.7: - -2010-05-04 Murray Cumming - - Documentation improvements. - - * docs/manual/libsigc_manual.xml: Remove Marshallers section because - it is apparently outdated and there is no example code to test it. - This fixes bug #417924 (Michael Ekstrand) - * sigc++/sigc++.h: Main page text: Rearranged slightly. - -2010-04-27 David King - - Improvements to main page documentation - - * sigc++/sigc++.h: Minor improvements. - -2010-04-23 David King - - Add main page to Doxygen documentation - - * docs/Makefile.am: Parse sigc++/sigc++.h for documentation. - * sigc++/sigc++.h: Add main page to Doxygen documentation. - -2010-04-23 David King - - Fix the functors Doxygen group in the m4 files - - * sigc++/functors/macros/functor_trait.h.m4: - * sigc++/functors/macros/mem_fun.h.m4: - * sigc++/functors/macros/ptr_fun.h.m4: Rename functors to - sigcfunctors. - -2.2.6: - -2010-04-16 Murray Cumming - - Docs: Fix the functors group and the link from the overview. - - * docs/website/doc.shtml: Revert this to point to the overview page at - docs/indeex.html, which I have manually uploaded to the website, until - we add this overview to the doxygen-generated documentation itself. - * sigc++/functors/slot_base.h: - * sigc++/visit_each.h: Rename the functors doxygen group to sigcfunctors, - because doxygen seems to confuse it with the one in libstdc++. - * docs/index.html: Update the links. - -2010-04-16 Murray Cumming - - Website: Fix the Makefile so upload works with sourceforge again. - -2010-04-06 Murray Cumming - - Website: Update the reference API link. - - * docs/website/doc.shtml: Update the reference API link to use - library.gnome.org. We should make sure that the tutorial docbook is there - too. - * docs/website/devel.shtml: Remove CVS-specific instructions, quickly - mentioning the git module instead. - However, the Makefile must be updated to cope with sourceforge's changes. - I was not able to upload this yet. - -2.2.5: - -2010-01-05 Daniel Elstner - - Use non-blurry font for dot graph labels - - * docs/reference/Doxyfile.in (SHOW_INCLUDE_FILES): Enable. - (SHOW_USED_FILES): Disable. - (DOT_FONTNAME): Change from FreeSans to Sans, as the hinting for the - former appears to be rather bad. - (TEMPLATE_RELATIONS): Disable to reduce noise. - -2009-12-29 Krzysztof Kosiński - - Accumulators: Allow return types that are different to the signal's. - - * sigc++/macros/signal.h.m4: signal_emit*: Correct the slot_iterator_buf_type - and slot_reverse_iterator_buf_type typedefs to allow accumulators with - return types that are different to the signal's return type. - * tests/Makefile.am: Reenable test_accumulated, so we can test the fix. - It should be manually disabled if building on AIX (if the AIX problem cannot - be fixed properly). - * tests/test_accumulated.cc: Add an accumulator with a return type that is - different to the signal's return type. In this case it's a vector listing - all results. - Bug #586436. - -2009-12-27 Daniel Elstner - - Disable collaboration graphs in documentation - - * docs/reference/Doxyfile.in (CLASS_DIAGRAMS): Enable. Contrary to - what the Doxygen documentation says, no dot class inheritance graphs - will be generated if both CLASS_DIAGRAMS and COLLABORATION_GRAPH are - set to NO. - (COLLABORATION_GRAPH), (GROUP_GRAPHS): Turn off additional graphs to - reduce the noise. - -2009-10-26 Armin Burgmeier - - * sigc++config.h: Move the first five definitions to the !SIGC_MSC - ifdef block, so MSVC does not see them and only uses the definitions - from the SIGC_MSC block. This fixes the build with MSVC. - -2009-09-19 Daniel Elstner - - Support Automake silent rules - - * configure.ac: Call the AM_SILENT_RULES macro if it is defined. - * docs/doc-manual.am, sigc++/Makefile.am: Prefix the commands of - custom rules with $(AM_V_GEN) or $(AM_V_at) in order to support - the silent rules feature of Automake. - -2009-09-17 Michael Hasselmann - - Documentation cleanup: sigc::hide() always only hides one signal argument - - * sigc++/adaptors/macros/hide.h.m4: The documentation stated that sigc::hide() - could discard multiple signal arguments when in fact the whole API only allows - control over one (dummy) signal argument at a time. The "multiple argument - hiding" example lives in it own section now to make it clearer you have to nest - sigc::hide() for that. - -2009-09-13 Daniel Elstner - - Enable verbose output of autoreconf - - * autogen.sh: Pass --verbose option to autoreconf. - -2.2.4.2: - -2009-09-02 Daniel Elstner - - Bump version to 2.2.4.2 and update NEWS - - * configure.ac (AC_INIT): Increment version number to 2.2.4.2. - (MM_PREREQ): Require mm-common 0.7.2. - * NEWS: Write news entry for libsigc++ 2.2.4.2. - -2009-09-02 Daniel Elstner - - Document namespace sigc briefly - - * sigc++/signal_base.h (sigc): Prepend documentation comment to - provide a brief description of namespace sigc, so that Doxygen - will recognize the namespace as documented. - -2009-08-31 Daniel Elstner - - Update Doxygen configuration for Doxygen 1.6.1 - - * docs/reference/Doxyfile.in: Update configuration template using - Doxygen 1.6.1. - (SORT_MEMBERS_CTORS_1ST): Enable. - -2009-08-31 Daniel Elstner - - Protect space after comma in M4 output - - * sigc++/macros/template.macros.m4 (_LOOP_SEP): Triple-quote the - list separator in this hairy construct, since the macro definition - itself is not quoted at all and the space after the comma got lost - in the output. This, in turn, produced overlong lines in the HTML - reference documentation. - -2.2.4.1: - -2009-08-28 Daniel Elstner - - Update news entry for libsigc++ 2.2.4.1 release - - * NEWS: Update top entry for release 2.2.4.1 of libsigc++. - (2.2.4): Correct spelling of Frédéric Péters' name. - -2009-08-27 Daniel Elstner - - Use shared mm-common Doxygen style sheet - - * configure.ac (MM_PREREQ): Require mm-common 0.7. - * docs/Makefile.am (dist_noinst_DATA): List doxygen.css. - * docs/reference/Doxyfile.in (HTML_STYLESHEET): Assign path - to the shared doxygen.css provided by mm-common. - -2009-08-27 Daniel Elstner - - Remove header and footer HTML fragments - - * docs/reference/libsigc_{header,footer}.html_fragment: Delete - files. These custom fragments were an unnecessary maintenance - hassle. Also, the files were out of date with respect to the - encoding and CSS classes used by Doxygen. - * docs/reference/Doxyfile.in (HTML_HEADER), (HTML_FOOTER): Set - to the empty string. - (PROJECT_NAME): Substitute @PACKAGE_NAME@. - (PROJECT_NUMBER): Substitute @PACKAGE_VERSION@. It does look - nicer in the generated HTML pages, and is probably also less - confusing. - (SORT_GROUP_NAMES): Enable for predictability. - -2009-08-26 Daniel Elstner - - Bump version to 2.2.4.1 and update NEWS - - * configure.ac (AC_INIT): Increment version number to 2.2.4.1. - * NEWS: Write news entry for libsigc++ 2.2.4.1. - -2009-08-26 Daniel Elstner - - Reenable hierarchy graphs for each class - - * docs/reference/Doxyfile.in (COLLABORATION_GRAPH): Set option - to YES to enable the per-class inheritance graphs. - -2009-08-25 Daniel Elstner - - Have Automake check NEWS and use bzip2 - - * configure.ac (AM_INIT_AUTOMAKE): Add options check-news and - dist-bzip2. - -2009-08-25 Daniel Elstner - - Update NEWS for libsigc++ 2.2.4 release - -2009-08-25 Daniel Elstner - - Bump version to 2.2.4 and require mm-common 0.6.1 - - * configure.ac (AC_INIT): Increase version number to 2.2.4. - (MM_PREREQ): Require mm-common 0.6.1 for the updated default - location of the reference documentation. - -2009-08-25 Daniel Elstner - - Change documentation host to library.gnome.org - - * README, docs/manual/libsigc_manual.xml: Adjust links to the - reference documentation in the text. - * docs/Makefile.am (pubdocbase), (htmlrefpub): Remove override - and use the updated mm-common default values. - * sigc++{,-uninstalled}.pc.in (htmlrefpub): Adjust link. - -2009-08-24 Daniel Elstner - - Add id="content" element to documentation index - - * docs/reference/libsigc_header.html_fragment: Start
element - with attribute id="content" to match the other C++ binding modules. - * docs/reference/libsigc_footer.html_fragment: Close
element. - -2009-08-20 Daniel Elstner - - Use new version component substitutions - - * MSVC_Net200[58]/sigc.rc.in: Replace the no longer defined - @FP_*_VERSION@ substitutions by the new @SIGCXX_*_VERSION@ - substitutions for the version number components. These are - defined by MM_INIT_MODULE() from mm-common. - -2009-08-20 Daniel Elstner - - Substitute API version in filenames dynamically - - * sigc++.pc.in: Rename file from sigc++-2.0.pc.in. - * sigc++-uninstalled.pc.in: Rename file from - sigc++-2.0-uninstalled.pc.in. - * MSVC_Net200[58]/sigc.rc.in: Rename files from sigc-2.0.rc.in - and use @SIGCXX_API_VERSION@ substitution for the API version. - Also replace @VERSION@ with @PACKAGE_VERSION@. - * MSVC_Net200[58]/libsigc++2.{sln,vcproj}: Remove version from - the project name and filenames. - * MSVC_Net200[58]/filelist.am: Remove version from filenames. - * configure.ac (AC_CONFIG_FILES): Insert ${SIGCXX_MODULE_NAME} - into output filenames and remove the version from the input - filenames. - * Makefile.am: Use $(SIGCXX_MODULE_NAME) in pkg-config file - names instead of hard-coding the API version. - * sigc++/Makefile.am (lib_LTLIBRARIES): Instead of hard-coding - the libtool archive name, substitute @SIGCXX_API_VERSION@ into - it, as well as into the derived variable names. - -2009-08-17 Daniel Elstner - - Set libtool version information - - * sigc++/Makefile.am (libsigc_2_0_la_LDFLAGS): Add libtool option - -version-info 0:0:0 to specify the version information explicitly. - -2009-08-16 Daniel Elstner - - Remove unused parameter names for correctness - - * tests/test_copy_invalid_slot.cc, tests/test_custom.cc, - tests/test_deduce_result_type.cc, tests/test_functor_trait.cc, - tests/test_limit_reference.cc: Remove the names of unused function - parameters from the prototype, in order to get libsigc++ to build - with fatal compiler warnings. - -2009-08-16 Daniel Elstner - - Rename scripts/ to build/ for consistency - - * build/: Rename directory from scripts/ for consistency with most - of the other modules that switched to the new build infrastructure. - * Makefile.am (ACLOCAL_AMFLAGS): Adjust M4 include directory. - * README: Adjust a reference to scripts/ in the text. - * configure.ac (AC_CONFIG_AUX_DIR): Copy auxiliary files to build/. - (AC_CONFIG_MACRO_DIR): Place Autoconf M4 files into build/. - * docs/Makefile.am: Include $(top_srcdir)/build/doc-reference.am. - -2009-08-16 Daniel Elstner - - Update for latest mm-common 0.4 - - * configure.ac (MM_PREREQ): Require mm-common 0.4. - (MM_INIT_MODULE): Omit now optional version number argument. - (MM_CONFIG_DOCTOOL_DIR): Copy the documentation utilities into docs/ - instead of scripts/. - * Makefile.am (dist_noinst_DATA): Remove documentation utilities. - * sigc++-2.0.pc.in (htmlrefpub): Append trailing slash. - * sigc++-2.0-uninstalled.pc.in (htmlrefpub): ditto, - * docs/Makefile.am (htmlrefpub): ditto. - (doc_input): Perform a VPATH search for each input file, to correctly - handle the case of rebuilding the documentation of a tarball release - which includes the generated sources. - (dist_noinst_DATA): List documentation utilities. - -2009-08-11 Daniel Elstner - - Do not recurse into MSVC subdirectories - - * MSVC_Net200[58]/filelist.am: New Automake include files, defining - the lists of files to ship from the MSVC project directories. - * MSVC_Net200[58]/Makefile.am: Delete recursive Makefile.am files. - * Makefile.am: Include MSVC_Net200[58]/filelist.am. - (dist_noinst_DATA): Distribute MSVC project files. - (SUBDIRS): Do not recurse into the MSVC_Net200[58] subdirectories. - * configure.ac (AC_CONFIG_FILES): Remove the output files - MSVC_Net200[58]/Makefile.am from the list. - (AC_CONFIG_COMMANDS): Copy sigc++config.h into the MSVC project - directories at the end of config.status. - -2009-08-11 Daniel Elstner - - Remove now superfluous doctool overrides - - * docs/Makefile.am: Remove overrides for the documentation - utilities, since MM_CONFIG_DOCTOOL_DIR() already takes care - of setting MMDOCTOOLDIR to the local directory. - * sigc++-2.0.pc.in (datadir): Substitute value, just in case. - -2009-08-10 Daniel Elstner - - Have mm-common-prepare install the doc utils - - * configure.ac: Call MM_CONFIG_DOCTOOL_DIR([scripts]) to set - up the destination directory for mm-common-prepare to copy - the documentation utilities to. - * scripts/doc-install.pl: Delete file. - * scripts/doc-postprocess.pl: ditto, - * scripts/tagfile-to-devhelp2.xsl: ditto. - -2009-08-09 Daniel Elstner - - Refresh doc-install and doc-postprocess copies - - * scripts/doc-install.pl, scripts/doc-postprocess.pl: Copy - latest versions from the mm-common module. - * docs/Makefile.am (doc_install), (doc_postprocess): Include - $(PERL) interpreter command in front of the script name. - -2009-08-08 Daniel Elstner - - Disable extraction of undocumented identifiers - - * docs/reference/Doxyfile.in (EXTRACT_ALL): Change setting to - NO, and adapt a number of related options accordingly. The - result is a net loss of about 300 generated .html files. The - roughly 450 files which remain now are still an insanely high - number, though. - (PREDEFINED): Predefine the Autoconf configuration defines to - nudge Doxygen towards documenting the canonical code paths. - -2009-08-07 Daniel Elstner - - Use #error explicitly instead of broken code - - * sigc++config.h.in: Do use the #error preprocessor directive, - instead of an errornous piece of code. This code does not need - the same level of obfuscation as an Autoconf feature test. - -2009-08-07 Daniel Elstner - - Change bug report URL to point to Bugzilla - - * configure.ac (AC_INIT): Change the bug-report argument to the - URL for filing a new libsigc++ bug on bugzilla.gnome.org. Also - name the website URL as fifth argument. It will simply be ignored - if the installed Autoconf does not support this new feature. - -2009-08-07 Daniel Elstner - - Do not enable -pedantic mode by default - - * configure.ac (MM_ARG_ENABLE_WARNINGS): Remove -pedantic from the - list of compiler flags to use at warning level "min" (the default). - -2009-08-07 Daniel Elstner - - Correct M4 forbidden tokens pattern - - * configure.ac (m4_pattern_forbid): Take into account that the - pattern is applied to tokens, not lines. Also catch unexpanded - calls to underscore-prefixed private macros. - -2009-08-06 Daniel Elstner - - Transition to new mm-common build infrastructure - - * autogen.sh: Replace with a minimal script that simply executes - mm-common-prepare, autoreconf and configure. - * configure.ac: Get rid of an enormous amount of old cruft. Use - macros from the new mm-common module to set up Doxygen for building - the documentation. Add option to enable more compiler warnings. - * sigc++-2.0-uninstalled.pc.in: New pkg-config data file to allow - linking to an uninstalled libsigc++. - * sigc++-2.0.pc.in: Modernize. Provide the location of the - installed reference documentation and the Doxygen tag file. - * sigc++config.h.in: Modernize and update for new build - infrastructure. - * Makefile.am, */Makefile.am: Modernize and adapt to the new C++ - binding build infrastructure in the mm-common module. - * sigc++/filelist.am: New Automake include file. Defines lists - of C++ and M4 source files. - * docs/Makefile.am: Rewrite using doc-reference.am from the - mm-common module. - * docs/doc-manual.am: New Automake include file for building the - libsigc++ Docbook manual. - * docs/images/Makefile.am: Remove file. - * docs/manual/Makefile.am: ditto, - * docs/reference/Makefile.am: ditto. - * docs/Makefile_web.am_fragment: Remove for now, to be taken care - of later. - * docs/reference/Doxyfile.in: Modernize and adapt to new build - infrastructure. - * docs/reference/beautify_docs.pl: Remove and use the more recent - scripts/doc-postprocess.pl instead. - * libsigc++-2.0.spec.in: Remove, to be resurrected only if someone - complains. - * scripts/Makefile.am: Remove file. Distribute the files from the - toplevel Makefile.am instead. - * scripts/cxx_std.m4: Add missing third argument to AC_DEFINE(). - * scripts/doc-install.pl: New file, copied from mm-common. - * scripts/doc-postprocess.pl: ditto, - * scripts/tagfile-to-devhelp2.xsl: ditto. - -2008-11-13 Murray Cumming - - * docs/website/stable.shtml: Correct the download link so it shows all - versions, not just 2.0. - -2.2.3: - -2008-10-08 Armin Burgmeier - - * MSVN_Net2005/libsigc++2.vcproj: Changed output name to match the new - naming convention. - - * MSVC_Net2008/: Added MSVC 2008 project files. These are basically - the same as for MSVC 2005, but converted to MSVC 2008 projects. - - * configure.ac: - * Makefile.am: Added the new files to the build. - -2008-08-08 Armin Burgmeier - - * MSVC_Net2005/libsigc++2.sln: Enable the disconnect_during_emit test - by default. - - * MSVC_Net2005/libsigc++2.vcproj: Renamed the generated debug database - file to sigc-2.0d.pdb (the default), to stay consistent with the *mm - wrapper libraries. - -2008-08-08 Armin Burgmeier - - * MSVC_Net2005/: Moved from MSVC_Net2003. - - * MSVC_Net2005/libsigc++2.sln: - * MSVC_Net2005/libsigc++2.vcproj: - * MSVC_Net2005/tests/*/*.vcproj: Converted the Visual Studio 2003 - project files to 2005 ones. - - * MSVC_Net2005/Makefile.am: - * Makefile.am: - * configure.ac: Adapted build files accordingly. - -2008-04-06 Cedric Gustin - - * MSVC_Net2003/sigc-2.0.rc.in: Removed ATL/MFC header files - dependency as afxres.h is not part of the Microsoft Platform - SDK provided with Visual C++ Express 2008. - Bug #503933. - -2.2.2: - -2008-03-10 Deng Xiyue - - * sigc++/macros/signal.h.m4: - * tests/test_accum_iter.cc: Add ifdefs around uses of - reverse_iterator to really fix the build with recent - versions of Sun CC. - Bug #302098. - -2.2.0: - -2008-01-01 Ryan Hill - - * tests/test_copy_invalid_slot.cc: Include the cstdlib - and cstring headers to fix the build with the gcc 4.3 - pre-release. Bug #454882. - -2007-08-31 Murray Cumming - - * tests/test_copy_invalid_slot.cc: Added some includes to - fix the build in some environments, such as when using Sun CC. - Thanks to Vladimir Marek in bug #469872. - -2.1.1: - -2007-08-14 Murray Cumming - - * sigc++/Makefile.am: - * sigc++/compatibility.h: Removed this header. - * sigc++/bind.h: - * sigc++/bind_return.h: - * sigc++/connection.h: - * sigc++/macros/class_slot.h.m4: - * sigc++/macros/hide.h.m4: - * sigc++/macros/method_slot.h.m4: - * sigc++/macros/object_slot.h.m4: - * sigc++/macros/retype.h.m4: - * sigc++/macros/signal.h.m4: - * sigc++/macros/slot.h.m4: - * sigc++/object.h: - * sigc++/retype_return.h: Removed deprecated - compatibility API, to probably fix the build with - some compilers, such as some versions of the Sun Forte C++ - CC compiler. Some of these headers are now mostly empty and - should be removed later. - This API has been deprecated April 2004, and - is not widely used, so it seems safe to do this now. - - * tests/Makefile.am: - * tests/test_compatibility.cc: Removed this test. - -2007-07-28 Michael Elkstrand - - * sigc++/macros/signal.h.m4: slot_iterator_buf, - slot_reverse_iterator_buf: Added typedefs for - value_type, reference, and pointer, so that these - iterators are more like standard C++ iterators, so they can - be used with standard C++ algorithms. - * tests/Makefile.am: - * tests/test_accum_iter.cc: Added a test for this. - Bug #417926. - -2006-11-14 Daniel Elstner - - * autogen.sh: Wholly replace this script with a critter from one - of my personal projects, with slight modifications. This one does - some sophisticated stuff like probing version numbers of available - automake and aclocal executables, in order to choose the right one - accordingly. All this is necessary to make the build system work - robustly in custom environments such as Maemo where automake-1.9 - doesn't come preinstalled. - -2006-06-20 Murray Cumming - - * sigc++/adaptors/macros/bind.h.m4: - * sigc++/adaptors/macros/retype.h.m4: - * sigc++/functors/macros/functor_trait.h.m4: - * sigc++/functors/macros/slot.h.m4: - * sigc++/macros/retype.h.m4: - * sigc++/macros/signal.h.m4: Revert the previous changes, because none is - used in the exported symbol names from gtkmm, so this would break the ABI - of gtkmm. - -2006-05-26 Régis Duchesne - - * sigc++/adaptors/macros/bind.h.m4: - * sigc++/adaptors/macros/retype.h.m4: - * sigc++/functors/macros/functor_trait.h.m4: - * sigc++/functors/macros/slot.h.m4: - * sigc++/macros/retype.h.m4: - * sigc++/macros/signal.h.m4: - Renamed 'nil' to 'none' to allow an Objective-C++ compiler to compile - the library header files. - -2005-12-21 Murray Cumming - - * sigc++/macros/signal.h.m4: Make remaining - reverse_iterator_buf operator--() methods - return by reference, like the operator++() methods. - Bug #304402 from John Profic. - -2005-12-20 Murray Cumming - - * sigc++/macros/signal.h.m4: Make all operator--() methods - return by reference, like the operator++() methods. - Bug #304402 from John Profic. - -2005-12-14 John Profic - - * sigc++/macros/signal.h.m4: Fix compilation problem in - the last patch. - -2005-12-14 John Profic - - * sigc++/macros/signal.h.m4: Added emit_reverse(). - -This is the HEAD branch, for API/ABI-compatible API additions. -See also the libsigc-2-0 branch. - -2005-12-01 Murray Cumming - - * sigc++/functors/slot_base.cc: - slot_base::disconnect(): Set call_ to 0, - to invalidate the slot, even if parent_ is 0. - I think parent_ is, for instance, a signal, but - disconnect should still work on a slot that is not - connected to a signal, because a slot can be invoked - directly. - Fixes bug #311057 from James Lin. - -2005-12-01 Murray Cumming - - * tests/Makefile.am: - * tests/test_slot_disconnect.cc: Added test - case from bug #311057. - -2005-11-16 Philipp Berndt - - * sigc++/adaptors/macros/exception_catch.h.m4: Make member - exception_catch_functor::catcher_ - public so that it can be accessed by visit_each() - (bug fixed for generalization on 2004-11-06) - -2.0.16: - -2005-08-01 Neal E. Coombes - - * sigc++/signal_base.h: Updated the documentation for temp_slot_list - as requested in bug #303896. - -2005-08-01 Murray Cumming - - * sigc++/adaptors/hide.h.m4: Added missing - ) in call to sun_forte_workaround(), fixing - build on SUN Forte 5.5. Bug #312020. - -2005-08-19 Bruno Martinez - - * sigc++/type_traits.h: Renamed - ::sigc::is_base_and_derived::internal to - ::sigc::is_base_and_derived::internal_class - in order to avoid conflict with - namespace internal. - -2005-07-13 Murray Cumming - - * docs/manual/libsigc_manual.xml: Correct mentions of - 1.2 stuff instead of 2.0. Patch in bug #310213 from - pebble.org.uk. - -2005-07-13 Murray Cumming - - * docs/manual/libsigc_manual.xml: Fixed typo - found by Antonio Coralles. - -2005-07-09 Murray Cumming - - * sigc++/macros/signal.h.m4: Did the same (see - last commit) for slot_const_iterator and - slot_iterator_buf. - -2005-07-09 Murray Cumming - - * sigc++/macros/signal.h.m4: slot_iterator: - operator--() now returns value, not reference, like - operator++() already did. This caused crashes when - using --no-inline with g++. Bug #308651 by - Michael Andres. - -2.0.15: - -2005-07-04 Philip Langdale - - * sigc++/adaptors/macros/compose.h.m4: Add a setter typedef to - compose*_functor and use it instead of the (incorrect) getter - typedef in the compose* specialization of visit_each<>(). - This corrects the lifetime management of slots created with - compose(). Bug #308433. - -2005-06-13 Marek Rouchal - - * tests/test_deduce_result_type.cc: Specify int return type - for main(), to be more ISO C++ compliant. Bug #307478. - -2005-06-11 Andris Pavenis - - * sigc++/adaptors/lambda/macros/base.h.m4: - * sigc++/adaptors/lambda/macros/select.h.m4 - * sigc++/adaptors/macros/hide.h.m4: Specify only a type (not a - parameter name) for unused member function parameters - -2005-06-12 Paul Pogonyshev - - * configure.ac: - * scripts/cxx.m4: - * sigc++config.h.in: Add test for whether the compiler allows - referencing to member functions of the class/structure being - declared from a definition of a static member variable. - Supposedly a generic solution for GCC 3.2 compilation problems. - - * sigc++/type_traits.h: Define SIGC_WRAP_IS_BASE_CLASS_ based on - results of the above test. - (struct is_base_and_derived): Wrap up is_base_class_() functions - in an internal class if SIGC_WRAP_IS_BASE_CLASS_ is defined. - -2005-06-10 Murray Cumming - - * sigc++/adaptors/macros/bind.h.m4: - * sigc++/functors/macros/slot.h.m4: - * sigc++/macros/signal.h.m4: Use CALL_SIZE instead of - hard-coded 7s and 6s. - -2.0.14: - -2005-06-10 Murray Cumming - - * sigc++/visit_each.h: Make the - limit_derived_target::with_type inner class an outer class, - to satisfy the SUN CC 5.7 compiler, though I think it is a - compiler bug. Bug #302098 has the test case. - -2.0.13: - -2005-06-07 Murray Cumming - - * tests/test_compatibility.cc: Specify the actual class when - using test_int(), instead of the derived class, to fix the build - on SUN Forte CC 5.5. Patch from Friedemann Kleint in - Bug #305647 - -2005-06-07 Murray Cumming - - * sigc++/macros/signal.h.m4: signal_emit::emit(): Use scope to - ensure a certain order of destruction of the member variables, to - avoid a leak on MSVC++. Patch by Andreas Ames in Bug #306249. - -2005-06-07 Murray Cumming - - * sigc++/macros/signal.h.m4: Added comments about commenting-out - SIGC_TYPEDEF_REDEFINE_ALLOWED when using SUN Forte CC 5.7, - because I can not seem to create a test for it. - -2005-06-07 Murray Cumming - - * configure.ac: - * scripts/cxx_std.m4: - * sigc++/macros/signal.h.m4: - * sigc++config.h.in: Added check for - the non-standard SUN Forte reverse_iterator<>, - and used it. This is based on the same stuff in - gtkmm. - -2005-06-07 Murray Cumming - - * sigc++/visit_each.h: limit_derived_target(): Just some whitespace - changes. - -2005-05-16 Neal E. Coombes - - * sigc++/signal_base.h: Modified temp_slot_list to be a temporary view - into a slot list. Instead of emptying the original it now simply tacks - a placeholder to the end of the original. It then uses this as it's - 'end' iterator. This should allow for conscious recursiveness, as well - as inserting a slot to any position in the slot list during emittion. - See bug #303896. - -2005-06-04 Friedemann Kleint - - * sigc++/macros/limit_reference.h.m4: - visit_each() template specializations: - Mention the bool I_derives_trackable - template type, to fix the build on Solaris - Forte 5.5. - -2.0.12: - -2005-05-06 Régis Duchesne - - * sigc++/macros/limit_reference.h.m4 (added): - * sigc++/Makefile.am: - New class that just stores a reference, and makes sure that if the - reference derives from trackable, then the trackable reference will be - used instead of the derived reference in visit_each(). - * sigc++/functors/macros/mem_fun.h.m4: Better fix for bug #169225 by - Régis Duchesne and Christian Hammond, based on the new limit_reference - class. - * sigc++/adaptors/bound_argument.h (added): New class (built upon the - new limit_reference class) that handles all 3 kinds of bound arguments: - by value, by reference, and by constant reference. References are - unwrapped in the bound_argument's constructor. - * sigc++/adaptors/macros/bind.h.m4: Fix for bug #302327 by Régis - Duchesne. Bound arguments now need to know whether they are passed by - reference or not. So bind() now builds bind_functor instances using - 'reference_wrapper' types, instead of 'Foo &' types. The - bind_functor code is modified to compensate. - * sigc++/adaptors/macros/bind_return.h.m4: Similar fix for a similar - bug (unfiled) with bound return arguments. - * sigc++/reference_wrapper.h: - * sigc++/type_traits.h: - The reference_wrapper class is only used in bound_argument.h. Put - correct but unused code under #if 0. - * sigc++/adaptors/lambda/base.h: This file needs reference_wrapper.h, - but was incorrectly relying on type_traits.h to include it. - * tests/Makefile.am: - * tests/test_virtualbase_delete.cc (deleted): - * tests/test_virtualbase_delete_ref_param.cc (deleted): - * tests/test_limit_reference.cc (added): - Replaced test_virtualbase_delete*.cc with a simpler - test_limit_reference.cc which checks for all 3 aspects of the same bug - in one file. - * tests/test_bind_ref.cc: Slots must use 'Foo &' types. We were lucky - this broken usage worked before this change. The change in - type_traits.h made this bug obvious, by preventing the code to compile. - * tests/test_bind_return.cc: After my change, bind() and bind_return() - must use 'reference_wrapper' types. - * tests/test_custom.cc: Made this test a no-op (so it does not perturb - 'make check' on released versions of the library) and made it a - template ready to be modified by hackers. - -2005-05-01 Murray Cumming - - * sigc++/functors/slot_base.cc: - slot_base::slot_base(src): If the source - slot_base has a null rep->call_, meaning that the - slot is invalid, just return a default-constructed - slot, to prevent the crash shown in - tests/tests_copy_invalid_slot.cc. Bug #302515 by - Régis Duchesne. - -2005-05-01 Murray Cumming - - * sigc++/functors/macros/mem_fun.h.m4: bound_*<>: - Add a new is_base_and_derived - parameter to the template and thereby provide a - specialization for T_Obj types that derive from - sigc::trackable. This prevents a crash when casting - from the derived type to sigc::trackable after the - derived destructor has run. This cast can sometimes - fail when using multiple inheritance, at least with - g++. Bug #169225 by Régis Duchesne and Christian - Hammond. - * sigc++/type_traits.h: Add documenation for - the internal is_base_and_derived<> template, which - allows us to specialize other templates for certain - template types. - -2005-04-28 Murray Cumming - - * sigc++/type_traits.h: Added comments for users of - g++ 3.2. - -2005-04-28 Murray Cumming - - * tests/Makefile.am: - * tests/test_virtualbase_delete.cc: Added - simplified test case from bug #169225. We have a patch - to make this succeed but I am not ready to commit it - just yet. - -2005-04-27 Murray Cumming - - * tests/Makefile.am: - * tests/test_custom.cc: - Added a place to put extra test code, so I don't have - to keep installing my crazy libsigc++ versions. - -2005-04-27 Murray Cumming - - * sigc++/visit_each.h: Revert back to the non-explicit - template call, because we can not specify the - template specialization so easily, because the - specializations have different numbers of types. - * tests/Makefile/am: - * tests/test_bind_ref.cc: Add a simple test only for - sigc::ref disconnection. - -2005-04-26 Murray Cumming - - * sigc++/visit_each.h: Use the explicit template - specialization, needed for Tru64 and AIX compilers. - This causes a crash in some uses of sigc::ref() - (when using g++ 3.3.4 or 3.3.5 , but not with 3.4) but - seems to fix a crash in some uses of multiple inheritance - (bug #169225). - * tests/test_bind.cc: Comment out the crashing (not with - g++ 3.4) use of sigc::ref() with an explanatory comment. - -2.0.11: - -2005-03-09 Cedric Gustin - - * Makefile.am: Moved MSVC_Net2003 directory to SUBDIRS. - * MSVC_Net2003/Makefile.am: Added blank.cpp to EXTRA_DIST. - * MSVC_Net2003/libsigc++2_msvcNet2003.sln: Removed - test_accumulated and test_lambda projects as the tests are - disabled in the standard, configure-based build. - * MSVC_Net2003/MSVC_Net2003/libsigc++2_msvcNet2003.vcproj: - Generate a PDB file in the Debug target. - -2005-03-05 Murray Cumming - - * docs/website/stable.html: Mention actual supported compilers. - * docs/website/docs.html: Removed broken examples links. Change - reference link to the reference overview page. - -2005-02-23 Murray Cumming - - * sigc++/functors/slot_base.h: Make slot_base::operator=() public, to - fix the build with SUN Forte C++ 5.5 and Tru64. - -2.0.10: - -2005-02-20 Murray Cumming - - * tests/test_slot.cc, test_disconnect.cc: #included to avoid - an unresolved symbol error with the Tru64 compiler. Solution found by - Tim Mooney in bug #161503. - -2005-02-20 Martin Schulze - - * sigc++/signal_base.h: Add some documentation. - -2005-02-20 Martin Schulze - - * sigc++/signal_base.cc: Reset deferred_ flag to false in - signal_impl::sweep() (Neal E. Coombes). Partly fixes bug #167714. - -2005-02-11 Martin Schulze - - * docs/manual/Makefile.am: Set the correct group in post-html. - -2005-02-11 Murray Cumming - - * docs/website/doc.shtml: Fix typo in url for reference docs. Found by - James Lin. - -2005-02-06 Murray Cumming - - * sigc++/signal_base.h: temp_slot_list::begin(), end(): Actually - return the iterators. - -2005-02-03 Neal E. Coombes - - * sigc++/signal_base.h: Add temp_slot_list struct to facilitate - allowing new connections to a signal during an emittion without - affecting that emittion. - * sigc++/macros/signal.h.m4: Use the new struct temp_slot_list to - prevent connections made during an emittion from being called in the - same emittion (which has the potential of causing things like - infinite loops). This guarantees an emittion will be finite, as well - as maintaining any order of emittion guarantees that may have already - been in place. - -2.0.9: - -2005-02-02 Murray Cumming - - * sigc++/visit_each.h: visit_each_type(): Reverted the change, so that - we do not specify the template types ot visit_each<>(), because it - crashes on g++ 3.3.4 (but not g++ 3.4.2). Added a comment telling users - of AIX (and maybe IRIX MipsPro and Tru64) to use the alternative version - if they have compilation problems. - -2005-02-01 Murray Cumming - - * sigc++/adapators/macros/base.h.m4: Add sigc::var<>() documentation, - from Roger Ferrer Ibáñez in bug #149483. - -2005-02-01 Murray Cumming - - * sigc++/adaptors/macros/compose.h.m4: In the template specializations - of visit_each(): As before, specify the specific other template - specializations of visit_each that we use. Needed by AIX. - * tests/Makefile.am: Reenabled most tests, because AIX can now - build them. - -2005-02-01 Murray Cumming - - * sigc++/visit_each.h: visit_each_type(): Specify the specific - template specialization of visit_each<>() to use. The AIX compiler, - and possibly the Tru64 compiler, need this extra hint. - -2005-02-01 Murray Cumming - - * bind.h.m4: Define bind_functor::operator() inline because the AIX - compiler/linker sometimes fails to find it when it is defined - outside of the class. - -2.0.8: - -2005-01-30 Murray Cumming - - * sigc++/type_traits.h: is_base_and_derived: Added - avoid_gcc3_warning_(), to avoid an incorrect warning when using - g++ 3.3.5 - -2005-01-28 Liza Klerck - - * sigc++/functors/macros/mem_fun.h.m4: Add a sigc:: namespace - prefix to the nested use of visit_each(), to avoid ambiguity when - using 2 versions of the libsigc++ API inside different namespace. - -2005-01-27 Murray Cumming - - * sigc++/adaptors/macros/adaptor_trait.h.m4: Add a sigc:: namespace - prefix to the nested use of visit_each(), to avoid ambiguity when - using 2 versions of the libsigc++ API inside different namespace, - which is not very advisable anyway. Bug #165222 from - liza at trdlnk.com. - -2.0.7: - -2005-01-24 Cedric Gustin - - * sigc++config.h.in : Moved the SIGC_USING_STD macro definition - out of the SIGC_CONFIGURE section. We also need it for MSVC. - * MSVC_Net2003/.cvsignore : Added .def and .aps files - * MSVC_Net2003/Makefile.am: Rewrote rule for local copy of - sigc++config.h (required for 'make distcheck'). - * MSVC_Net2003/libsigc++2_msvcNet2003.sln: Added test_retype and - test_disconnect_during_emit tests. - * MSVC_Net2003/tests/test_disconnect_during_emit/*, - MSVC_Net2003/tests/test_retype/*: Initial commit. - -2005-01-21 Murray Cumming - - * tests/: Disabled the test_accumulator, test_bind, and test_compose - tests, and part of test_mem_fun because the AIX xlC compiler can not - build them, but it can still do most things, including the examples. - See the comments in tests/Makefile.am. - -2005-01-21 Murray Cumming - - * sigc++/adaptors/bind.h.m4: non-member operator()(): Specify the - extra nil arguments in the templated class name prefix. Oddly, the - AIX xlC compiler says that the type of the first parameter does not - match the template if you don't do this. - -2005-01-21 Murray Cumming - - * sigc++/type_traits.h: is_base_and_derived struct: Move the - is_base_class_() functions out of the inner class, because the AIX - xlC compiler does not like that - see the comments in the code. - * sigc++/adaptors/bind.h.m4: Add the extra nil template types to - the template specializations, as in slot and signal. - -2005-01-21 Murray Cumming - - * sigc++/functors/macros/slot.h.m4, sigc++/macros/signal.h.m4: - slot and signal template specialization for - various numbers of template args: In the class slot line, specify - all the remaining template types as null, instead of expecting the - compiler to guess them in itself. This partly fixes the build on - AIX with the xlC compiler. Bug #164685. - -2005-01-19 Murray Cumming - - * sigc++/type_traits: struct is_base_and_derived: Make the test inner - struct a friend, so that it can use the big inner struct. This is - required by the Tru64 compiler. - * sigc++/adaptors/lambda/base.h: Put the unwrap_lambda_value() - definitions at the top, because Tru64 (understandably) needs them to - be declared before use. - -2005-01-19 Murray Cumming - - * scripts/: Added cxx_std.m4, with a test copied from - glibmm/scripts/cxx_std.m4 to check if the compiler has the std:: - namespace. - * sigcconfig.h: #undef the new #define and add SIGC_USING_STD(), - like GLIBMM_USING_STD, to put stuff in the std:: namespace when it - is not there already, - * configure.in: Used the new test. - * tests/*: Uses SIG_USING_STD() for every std:: thing that we use. - This is needed by the Tru64 and HP-UX compilers when using their - defaults. - -2005-01-19 Murray Cumming - - * configure.in: AC_INIT(): Provide the extra tarball name parameter, - so that it does not create a libsigc--- tarball. - -2005-01-19 Murray Cumming - - * configure.in: AC_INIT(): Use libsigc++ instead of sigc++, attempting - to get the correct tarball name. - -2005-01-18 Murray Cumming - - * configure.in: Used the autoconf 2.93 and AM_INIT_AUTOMAKE() - technique to specify ustar format for the tarball, to prevent files - with long file names from appearing at the top of the tarball. - Based on the same fix in gtkmm 2.6. - -2005-01-18 Murray Cumming - - * sigc++/functors/macros/slot_h.m4: Specify the base class when - using the rep_ member variable. This stops the HP-UX aCC compiler - from saying that a Nonstatic member is referenced in a nested class, - local class or static member initializer. Bug #150719. - -2005-01-18 Murray Cumming - - * Bug #159597 - patch from e97_far at e.kth.se to replace C-style - casts with reinterpret_cast<> and static_cast<> to avoid warnings. - -2005-01-17 Murray Cumming - - * docs/manual/Makefile.am: Specifying html/index.html instead of - just the html directory as a target seems to fix distcheck problems. - I can also now confirm that the install works on solaris, when using - gmake, though not when using make. - -2005-01-17 Murray Cumming - - * MSVC_Net2004/Makefile.am: Add built files to DISTCLEANFILES to fix - the distcheck. - * docs/reference/Makefile.am, manual/Makefile.am: Specify $srcdir in - paths, to fix distcheck of the manual, and maybe fix install problems - on Solaris. - -2005-01-11 Murray Cumming - - * docs/website/stable.html: Updated the text about binary packages. - * docs/website/docs.html: Link to the 2.0 documentation instead of the - 1.2 documentation. - -2004-12-17 GregSchussman - - * glossary.shtml: Clean up punctuation, make definitions complete - sentences, and add clarifications for certain definitions according to - what Murray Cumming's suggestions and answers to my questions. - Bug #161580. - -2005-01-11 Murray Cumming - - * docs/: Added manual, copied from the libsigc++-1.2 cvs module, - and updated it for the new 2.0 API. - -2005-01-11 Murray Cumming - - * docs/: Added website, copied from the libsigc++-1.2 cvs module. - We will use it from here from now on. - -2004-12-11 Cedric Gustin - - * configure.ac : parse version tags at configure time (for - sigc-2.0.rc). - * MSVC_Net2003/sigc-2.0.rc.in : New resource file. - * MSVC_Net2003/Makefile.am: include sigc-2.0.rc in distribution. - -2004-12-08 Cedric Gustin - - * MSVC_Net2003/Makefile.am: get sigc++config.h from $(top_builddir) - instead of $(top_srcdir). - -2004-12-08 Cedric Gustin - - * MSVC_Net2003/*/*.vcproj: Renamed libsigc++ target to - sigc-2.0d.dll (Debug) and sigc-2.0.dll (Release). Added - $(SolutionDir) and $(SolutionDir)\.. to "Additional Include - Directories" in tests projects. - * sigc++config.h.in: Rewrote dllexport/dllimport macros for - MSVC, for better consistency with glibmm/gtkmm. - * MSVC_Net2003/Makefile.am: copy sigc++config.h from $(top_srcdir) - at build time. - -2004-11-27 Murray Cumming - - * configure.in: Revert the AC_PROG_LIBTOOL change, so that this builds - with actually released libtool versions, and in jhbuild, so that it - gets testing. - -2004-11-06 Martin Schulze - - * sigc++/adaptors/macros/exception_catch.h.m4: Make catcher_ member - public so that it can be accessed by visit_each() (bug reported on - ml by Philip Langdale ). - -2004-10-24 Martin Schulze - - * MSVC_Net2003/*/*.vcproj: Link with the "multithreaded DLL" runtime - libraries and enable RTTI for the MSVC build - (patch from Timothy M. Shead ). - * MSVC_Net2003/*/.cvsignore: Hide generated build files from cvs - (patch from Timothy M. Shead ). - -2.0.6: - -2004-10-12 Martin Schulze - - * MSVC_Net2003/*/*.vcproj, MSVC_Net2003/blank.cpp: Fix project files - to compile out-of-the-box and add dummy file so that .cc files get - recognized as c++ code files (patch from Timothy M. Shead). - -2004-10-10 Martin Schulze - - * sigc++/signal_base.{h,cc}, sigc++/functors/slot_base.{h,cc}, - sigc++/functors/macros/slot.h.m4: If SIGC_NEW_DELETE_IN_LIBRARY_ONLY - is defined, implement signal_base::operator new/delete and - slot_rep::operator new/delete (suggested by Timothy M. Shead). - Remove old work-around from 2004-10-02 since it didn't work. - -2004-10-07 Martin Schulze - - * configure.ac: Update for libtool 1.5a (with support for Intel C++). - * MSVC_Net2003/sigc++config.h: Remove bogus '#define' - (reported by Timothy M. Shead ). - -2004-10-02 Martin Schulze - - * configure.ac: Bump version number to 2.0.6. - * NEWS: Add ChangeLog summary for version 2.0.6. - -2004-10-02 Martin Schulze - - * sigc++/functors/slot_base.{h,cc}, sigc++/functors/macros/slot.h.m4: - Rename (typed_)slot_rep::detach to (typed_)slot_rep::destroy. - Call the dtor of the functor stored in typed_slot_rep from destroy(). - A cleaner solution would be to add an additional "virtual" function - that calls 'delete' or a real virtual dtor. However, this would be - less efficient and might break the ABI. (Fixes #152323.) - -2004-10-02 Martin Schulze - - * sigc++config.h.in, MSVC_Net2003/sigc++config.h, - sigc++/signal_base.cc, sigc++/functors/slot_base.{h,cc}, - sigc++/functors/macros/slot.h.m4: Define and use new macro - SIGC_NEW_DELETE_IN_LIBRARY_ONLY to ABI-compatibly move - all calls to new and delete into non-inline library code. - -2004-09-26 Martin Schulze - - * sigc++/adaptors/lambda/macros/group.h.m4: Add a missing - template keyword in the definition of deduce_result_type::type - (hopefully fixes #152327). - -2004-09-26 Martin Schulze - - * sigc++/macros/object_slot.h.m4: Use correct bound_mem_functor - variants for const (volatile) methods (fixes #148744). - -2004-09-01 Martin Schulze - - * docs/index.html: Correct link to lambda module. - -2004-09-01 Martin Schulze - - * README: Update compatibility section. - -2.0.5: - -2004-09-01 Martin Schulze - - * MSVC_Net2003/Makefile.am: Add sigc++config.h to EXTRA_DIST. - * configure.ac: Bump version number to 2.0.5. - * NEWS: Add ChangeLog summary for version 2.0.5. - -2.0.4: - -2004-08-21 Martin Schulze - - * tests/test_lambda.cc: Use sigc::var("\n") instead of sigc::ref("\n"). - Comment out the affected lines, nevertheless. - Sun FORTE and Compaq C++ can handle neither sigc::ref("\n") nor - sigc::var("\n"). I see more chances fixing sigc::var("\n"). - * sigc++/adaptors/lambda/macros/base.h.m4: Add a comment about a - possible work around for sigc::var("\n") compiler problems. - * tests/test_compatibility.cc: Remove a 'const' keyword that prevents - the test case from compiling with the Sun FORTE. - * tests/test_trackable.cc: Remove a 'virtual' keyword and an unused - variable to avoid compiler warnings. - * NEWS: Add ChangeLog summary for version 2.0.4. - -2004-08-03 Martin Schulze - - * scripts/cxx.m4, sigc++config.h.in, configure.ac, - sigc++/adaptors/lambda/macros/operator.h.m4, tests/test_lambda.cc: - Rollback change from 2004-07-15: configure check - SIGC_OPERATOR_OVERLOAD_AMBIGUITY is not needed - the overload - ambiguity doesn't occur if the lambda operators take all arguments - as const reference. - * configure.ac: Bump version number to 2.0.4. - -2004-08-03 James Lin - - * Added SIGC_API qualifier to all externally-visible non-template - classes/structs. - * Added #include to the files that use SIGC_API. - * Added empty SIGC_API definition to sigc++config.h.in for non-MSVC - compilers. I'm not sure if this is the right place to put this - (probably not). - * Added MSVC-specific sigc++config.h to the MSVC project directory. - (The comment in it probably should be edited.) - * Changed MSVC project settings to output a multi-threaded DLL, set - the include paths to work (hopefully) out-of-the-box. Disabled - precompiled headers, since they just complicate things and - shouldn't be necessary for such a relatively project. - -2004-08-01 Martin Schulze - - * sigc++/type_traits.h: Remove type_trait<>::instance() - (was unimplemented and unused; caused problems with the MSVC). - -2004-07-23 Martin Schulze - - * Makefile.am: Fix typo concerning distribution of libsigc++-2.0.spec. - * AUTHORS: Mention our contributors for platforms Sun FORTE and Intel C++. - -2004-07-15 Martin Schulze - - * *.h.m4: Don't call operator()() in sun_forte_workaround(); rather copy - operator()(). Calling operator()() makes a copy of the arguments causing - wrong results if an argument type is a reference. Hopefully fixes #147311. - -2004-07-15 Martin Schulze - - * tests/test_lambda.cc: Break "std::cout << [expr] << a << std::endl;" - into "std::cout << [expr]; std::cout << a << std::endl;". - I hope this fixes #147313 where the right values for "[expr]" but wrong - values for "a" were written to std::cout for some compiler with optimizations - turned off. - -2004-07-15 Martin Schulze - - * sigc++/adaptors/lambda/macros/operator.h.m4: Correct return type deduction - of lambda expressions in lambda_operator*::operator()(). Might be related to - bug #147313. - * sigc++/adaptors/lambda/macros/group.h.m4: Use m4 macro _P_(). - -2004-07-15 Martin Schulze - - * scripts/cxx.m4, sigc++config.h.in, configure.ac, - sigc++/adaptors/lambda/macros/operator.h.m4, tests/test_lambda.cc: - Add configure check SIGC_OPERATOR_OVERLOAD_AMBIGUITY for a SUN FORTE - compiler problem (bug #147391). Use it to decide whether the lambda - action operators may be overloaded (not doing so restricts the API slightly). - * sigc++/adaptors/lambda/macros/operator.h.m4: Add some doxygen comments - and remove attic code. - * sigc++/adaptors/lambda/macros/base.h.m4: - Add templates unwrap_lambda_type and unwrap_lambda_value() to support - the non-overloaded lambda action operators. Also add some doxygen comments - and remove attic code. - * sigc++/adaptors/lambda/macros/group.h.m4: Fix a bug that resulted in - gargabe values being passed on to the functor contained in the group adaptor - (partly fixes #147313). - -2004-07-11 Martin Schulze - - * scripts/cxx.m4, sigc++config.h.in, configure.ac, *.h.m4: - Split SIGC_CXX_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - into SIGC_CXX_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - and SIGC_CXX_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD. - Remove LIBSIGC_TEMPLATE_PREFIX. Add template keyword to - SIGC_WORKAROUND_OPERATOR_PARENTHESES depending on the configure checks. - Should fix the compiler problems with MSVC. - -2004-07-11 Martin Schulze - - * examples/hello_world.cc: Use sigc::ptr_fun instead of std::ptr_fun. - (fixes bug #144846) - -2004-07-11 Eric Bourque - - * libsigc++-2.0.spec.in: new file - * configure.ac : patched generate spec file - * .cvsignore: ignore generated file (Martin Schulze) - * Makefile.am: distribute spec file (Martin Schulze) - -2004-07-11 Murray Cumming - - * sigc++/connection.cc: Added some comments. - * sigc++/trackable.cc: operator=(): Check for self-asignment, though I - do not know of any actual bug that this fixes. Added some comments. - * sigc++/trackable.h Added some doxygen documentation. - -2004-07-09 Murray Cumming - - * tests/: Added test_disconnect_during_emit.cc, to prove that this - works. - -2004-07-08 Murray Cumming - - * tests/test_retype_return.cc: foo::operator(int): return a - value. The SUN Forte 5.5 compiler complains about this, as it should. - -2004-07-08 Murray Cumming - - * sigc++/macros/signal.h.m4: class signal*: Rename the slot_list - typedef to slot_list_type, because there is already a template class - called slot_type. SUN Forte 5.5 seems to complain about this and I am - not surprised. The old typdef is still there for backwards - compatibility, except when building with SUN Forte. - -2004-07-07 Murray Cumming - - * scripts/cxx.m4: SIGC_CXX_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD(): - Don't define the SIGC_TEMPLATE_SPECIALIZATOIN_OPERATOR_OVERLOAD C - macro at all if the test fails. This might fix the build on SUN Forte. - * sigc++/functors/macros/mem_fun.h.m4: Default constructor: Initialize - the func_ptr_ member variable. I have no evidence that this solves any - problems, but it worried me. - * sigc++/functors/slot_base.h: operator bool(): Correct documentation, - to use @code instead of - * sigc++/macros/signal.h.m4: Remove the documentation for the - parameters named first and last, because they do not exist. - -2004-05-31 Martin Schulze - - * autogen.sh: Add '--force'-flag to the 'libtoolize'-command (bug #143425). - -2.0.3: - -2004-05-30 Martin Schulze - - * configure.ac: Bump version number to 2.0.3. - * NEWS: Add ChangeLog summary for version 2.0.3. - * sigc++/macros/signal.h.m4: Fix segfault on emission of unconnected signal. - * tests/test_signal.cc, tests/test_accumulated.cc: Emit unconnected signal. - * sigc++/macros/object_slot.h.m4: Suppress compiler warning at - dynamic_cast<>-test (tested by Christof Petig/Timothy M. Shead). - -2.0.2: - -2004-05-22 Martin Schulze - - * configure.ac: Bump version number to 2.0.2. - * NEWS: Add ChangeLog summary for version 2.0.2. - -2004-05-20 Martin Schulze - - * sigc++/macros/signal.h.m4: If a custom accumulator is specified - invoke it on signal emission even if the signal's slot list is empty. - (This used to be the case in libsigc++-1.2 as pointed out by Timothy.) - -2004-05-20 Martin Schulze - - * sigc++/macros/object_slot.h.m4: Suppress compiler warning at - dynamic_cast<>-test (suggested by Timothy M. Shead). - -2004-05-01 Martin Schulze - - * README: Updated for libsigc++-2.0. - -2.0.1: - -2004-04-27 Martin Schulze - - * configure.ac: Bump version number to 2.0.1. - * NEWS: Add ChangeLog summary for version 2.0.1. - * sigc++/adaptors/lambda/macros/base.h.m4: Fixed documentation. - * sigc++/adaptors/macros/bind.h.m4: Hide work-arounds from doxygen. - * scripts/cxx.m4, sigc++config.h.in, configure.ac, - sigc++/adaptors/macros/bind.h.m4: Removed configure check. It - showed that the Apple gcc can also compile the sophisticated version - of the work-around. - -2004-04-26 Martin Schulze - - * sigc++/macros/object_slot.h.m4: Modified test for SigC::Object - inheritance so that it also works if SigC::Object is virtual base. - (Fixes bug 141094 reported by Jonathan Brandmeyer) - -2004-04-26 Martin Schulze - - * scripts/cxx.m4: Updated the configure check. It would probably - have succeeded on the Apple. - -2004-04-26 Martin Schulze - - * sigc++/adaptors/macros/bind.h.m4: Add work-arounds for - bind<-1>::deduce_result_type compilation error on Apple gcc 3.3. - * scripts/cxx.m4, sigc++config.h.in, configure.ac: Add configure - check for the compilation error above. - * sigc++/adaptors/lambda/macros/operator.h.m4: Replace _A with - _Aa. _A is a reserved keyword on Apple gcc 3.3 (Spundun Bhatt). - (fixes bug #10444 reported by Spundun Bhatt) - -2004-04-19 Martin Schulze - - * sigc++/signal_base.cc: Fixed serious bug in signal_base::impl(): - Only reference a newly created object (initial reference). - (This fixes bug #140269 reported by Andris.) - -2004-04-19 Murray Cumming - - * scripts/cxx.m4: Updated the operator() template check, because it - failed with gcc 3.4 (from cvs). Apparently the template keyword can - only be used from another template. - -2.0.0: - -2004-04-06 Martin Schulze - - * configure.ac: Bump version number to 2.0.0. - * NEWS: Add ChangeLog summary for version 2.0.0. - * TODO, AUTHORS: Bring up to date. - * sigc++-2.0.pc.in, Makefile.am: 1.9 -> 2.0 - * Added more documentation. - -2004-04-10 Murray Cumming - - * sigc++/connection.[h|cc]: Implement blocked() to avoid undefined - symbol linker error. - -2004-04-08 Murray Cumming - - * dist the scripts directory. - -1.9.16: - -2004-04-06 Martin Schulze - - * configure.ac: Bump version number to 1.9.16. - * NEWS: Add ChangeLog summary for version 1.9.16. - -2004-04-02 Murray Cumming - - * sigc++/connection.cc: Make block() and unblock() always return a - value, to fix compiler warnings. Patch from bug #138620 by - Alexander Nedotsukov. - -2004-04-02 Murray Cumming - - * Fix the compile of examples/member_method.cc. Bug #131701 from - Kirill Smelkov. I also made the examples build as part of the regular - build. - -2004-04-02 Murray Cumming - - * sigc++config.h.m4: Remove every undef apart from the one we need, to - avoid clashes, because we #include this in a public header. - -2004-03-25 Murray Cumming - - * scripts/cxx.m4, configure.in, sigc++config.h.in: Rename the - template_keyword check to template_specialization, because the problem - is with or without the keyword. - * sigc++/adaptors/macros/adaptor_trait.h.m4: Define - SIGC_WORKAROUND_OPERATOR_PARENTHESES, which calls either operator() or - sun_forte_workaround() depending on the result of the compiler test. - * many .m4 files: Add sun_forte_workaround methods that call the - operator() methods. Put them in #ifdefs so that only SUN Forte C++ - sees them. - -2004-03-22 Murray Cumming - - * Makefile.am, sigc++/Makfile.am: Fix the sigc++config.h.in disting, - to fix make distcheck. - -2004-03-21 Murray Cumming - - * Rename config.h.in to sigc++config.h.in so that gtkmm does not - include some other config.h at strange times - fixes a problem in - the gtkmm demos. This should really be in the sigc++ directory, but - that seems to add that as an include path, which causes the STL - headers to include sigc++/signal.h instead of some STL signal.h header. - -2004-03-20 Murray Cumming - - * Makefile.am: Install the config.h platform-specific header. - * sigc++-2.0.pc.in: Report the include path for config.h - -2004-03-20 Murray Cumming - - * Added config.h.in, using autoheader, from which config.h will be - generated, so we can detect compiler features. - * configure.ac: Added AC_CONFIG_HEADER(config.h) to generate config.h - from config.h.in. - * scripts/cxx.m4: Added this directory and file, with a - SIGC_CXX_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD macro that defines - the SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD C macro. - * autogen.sh: Added -I scripts to the aclocal call, so that it finds - the m4 macro for configure.ac. - * sigc++/adapators/macros/adaptor_trait.h.m4: Include config.h and - use SIGC_TEMPLATE_KEYOWRD_OPERATOR_OVERLOAD. - -2004-03-18 Martin Schulze - - * tests/test_mem_fun.cc, tests/test_ptr_fun.cc: Don't test - making functors from overloaded methods with partial template - specialization. Not portable among different compilers (SUN FORTE). - * adaptors/macros/apdaptor_trait.h.m4: Only gcc seems to use the - notation A.template operator()<...>(...) => adapt preprocessor check - for #define LIBSIGC_TEMPLATE_PREFIX. TODO: replace with configure check. - -2004-03-13 Murray Cumming - - * g++ 3.4 (pre-release) build fixes: - * sigc++/macros/signal.h.m4: slot_iterator_buf::operator*(): - Use blocked() and empty() instead of non-existant blocked_and_empty(). - * sigc++/functors/macros/mem_fun.h.m4: memfun_functor*::operator()(): - Use this->func_ptr_ instead of just func_ptr_. - * sigc++/adaptors/macros/deduce_result_type.h.m4: Use - T_functor::template deduce_result_type<> instead of just - T_functor::deduce_result_type<>. - * sigc++/adaptors/lambda/macros/base.h.m4, operator.h.m4, group.h.m4:: - Use template keyword again. operator[](): Use this->value_ instead of - just value_. - * sigc++/adaptors/lambda/macros/bind/m4: Use template keyword, and - this-> again. - * sigc++/adaptors/macros/compose.h.m4, hide.h.m4, bind_return.h.m4, - exception_catch.h.m4: - rettype.h.m4, rettype_return.h.m4: Use template keyword,and this-> again - -1.9.15: - -2004-02-27 Martin Schulze - - * configure.ac: Bump version number to 1.9.15. - * NEWS: Add ChangeLog summary for version 1.9.15. - -2004-02-27 Martin Schulze - - * sigc++/functors/macros/slot.h.m4: Make the unnumbered slot templates' - copy ctors use the copy ctors of the base class. Fixes bug #24698. - * tests/test_slot.cc: Test copy ctor (Bryan Forbes). - -2004-02-27 Martin Schulze - - * tests/type_functor_trait.cc: Bring it up-to-date (use sigc::ref). - Make it work with the SUN Forte. - -2004-02-24 Martin Schulze - - * sigc++/type_traits.h: Make is_base_and_derived<> work with the SUN Forte. - -2004-02-19 Martin Schulze - - * sigc++/type_traits.h: Make is_base_and_derived<> platform independant. - * sigc++/adaptors/lambda/macros/base.h.m4: Make lambda_core<> ctors - explicit. Remove an unused ctor from lambda_core. - -2004-02-14 Martin Schulze - - * sigc++/functors/slot_base.h, sigc++/functors/macros/slot.h.m4: - Move some documentation to slot_base.h. - * sigc++/signal_base.h, sigc++/macros/signal.h.m4: - Move some documentation to signal_base.h. - - API addition: - * sigc++/functors/macros/slot.h.m4: Add numbered slot# templates. - Make unnumbered slot templates inherit from slot#. - - API change: - * sigc++/functors/macros/mem_fun.h.m4: Allow for methods of the object's - base types to be passed into sigc::mem_fun(). (Used to be the case in - libsigc++-1.2). - -2004-02-13 Murray Cumming - - * sigc++/functors/slot_base.[h|cc], sigc++/trackable.[h|cc]: Create - and use a typedef for the destroy_notify callback functions, to avoid - confusion function pointer declaration syntax in the API. - -2004-02-13 Murray Cumming - - * Moved implementation to .cc files: - * sigc++/functors/: Added slot_base.[h|cc] which contains non-template - code that was previsouly in the generated functors/slot.h and - non-generated slot.cc files. All non-inline implementation is now in - the .cc file. - * sigc++/functors/macros/slot.m4: Removed the code that has been moved - to slot_base.[h|cc]. - * sigc++/: Added signal_base.[h|cc] which contains non-template code - that was previously in the generated signal.h and non-generated - signal.cc file. All non-inline implementation is now in the .cc file. - * sigc++/macros/signal.m4: Removed the code that ahs been moved to - signal.cc - * sigc++/connector.[h|cc]: method implementation moved to the .cc file. - -1.9.14: - -2004-02-13 Martin Schulze - - * configure.ac: Bump version number to 1.9.14. - * NEWS: Add ChangeLog summary for version 1.9.14. - -2004-02-09 Murray Cumming - - * sigc++/functors/macros/slot.h.m4: slot_base: Added operator bool(), needed to - check for a slot that is created with the default constructor. This was - present in libsigc++ 1.2 also. - -2004-02-06 Murray Cumming - - * Makefile.am: Build the docs directory, by adding it to SUBDIRS. - * docs/Doxyfile.in: Updated to be more glibmm-like. - * Added some @deprecated doxygen bits. - * sigc++/macros/signal.h.m4: Call base constructor from signal_base - constructor - this is an error-as-warning when building gtkmm. - -1.9.13: - -2003-11-30 Martin Schulze - - * configure.ac: Bump version number to 1.9.13. - * NEWS: Add ChangeLog summary for version 1.9.13. - * Makefile.am, MSVC_Net2003/Makefile.am, configure.ac: - Distribute MS .Net project files. - * sigc++/adaptors/macros/[bind,hide].h.m4: Correct and add - documentation. Make hide_functor ctor explicit. - -2003-11-11 Martin Schulze - - * sigc++/adaptors/macros/[bind,hide].h.m4: Change to zero-based - argument index in numbered bind() and hide() overload - (Agreement on the mailing list). - Support binding up to CALL_SIZE arguments with one bind adaptor. - (Requested by joey yandle and others). - Only support binding of multiple arguments in unnumberd overloads - to keep the API simple (Requested by Murray Cumming). - * tests/test_[bind,hide,functor_trait].cc, sigc++/bind.h: - Reflect API changes in compatibility module and test cases. - -2003-11-10 Martin Schulze - - * sigc++/adaptors/macros/[bind,hide].h.m4: Add unnumbered - bind() and hide() overloads to make specifying the argument - position optional (Proposed by Jeff Franks). - * tests/test_[bind,hide].cc: Test unnumbered bind() and hide(). - * sigc++/adaptors/macros/adaptor_trait.h.m4: - Change "#ifdef MSVC" to "#ifdef _MSC_VER" (Roel Vanhout). - -2003-11-09 Martin Schulze - - * sigc++/functors/macros/slot.h.m4: Change functor type in - typed_slot_rep to adaptor_trait::adaptor_type - and use explicit function template instantiation in - internal::slot_call::call_it(). Avoids copying of arguments - in call_it() and enables binding of object instances - to class methods through bind() (Reported by Jeff Franks). - * tests/test_bind.cc: Test binding object instances to - class methods through bind(). - * sigc++/adaptors/adaptors.h: Include retype[_result].h. - * sigc++/adaptors/macros/adaptor_trait.h.m4: - - Add documentation. - - Mark some c-tors as explicit. - - Remove ununsed operator T_functor&() from adaptor_functor. - * sigc++/adaptors/macros/deduce_result_type.h.m4: - Rewrite parts of the documentation. - * sigc++/adaptors/macros/bind.h.m4: Add documentation. - * sigc++/functors/macros/mem_fun.h.m4: Remove unnecessary - explicit markers. Minor fixes to documentation. - * sigc++/functors/macros/functor_trait.h.m4: - Minor fixes to documentation. - -1.9.12: - -2003-11-04 Martin Schulze - - * configure.ac: Bump version number to 1.9.12. - * NEWS: Add ChangeLog summary for version 1.9.12. - -2003-11-03 Martin Schulze - - * sigc++/macros/signal.h.m4: Document accumulators. - Move slot_iterator_buf into namespace internal. Since - accumulators have the iterator type as a template argument - there is no need to expose this very internal type. - * sigc++/functors/macros/*.m4: Regroup documentation. - Documentation of the core parts of the library should be - complete by now. - -2003-11-02 Martin Schulze - - * Improve documentation of the core parts of the library. - * tests/test_ptr_fun.cc: Test ptr_fun() with static - member functions. - -2003-11-02 Martin Schulze - - * Move all .m4 files into new subdirectories - sigc++/[...]/macros. Install the .m4 files on - "make install" (Reported by Ron Steinke). - -2003-11-01 Martin Schulze - - * sigc++/[class,method,object]_slot.h.m4: Include - sigc++/functors/mem_fun.h (Reported by Ron Steinke). - -2003-11-01 Martin Schulze - - * sigc++/adaptors/lambda/operator.h.m4: Add negation - operator I have completely overlooked until now. - * sigc++/tests/test_lambda.cc: Test negation operator. - -2003-11-01 Martin Schulze - - * sigc++/[class_slot,method_slot,object_slot,hide].h.m4, - sigc++/signal.h.m4, sigc++/functors/mem_fun.h.m4: - - Use a shorter notation for ..._mem_function variants. - - Change order of mem_funcotr<>'s template arguments to - match std::mem_fun_t and to be more consistent with adaptors. - - Use ::sigc::slot's implicit ctor in compatibility module. - * sigc++/adaptors/lambda/operator.h.m4: Change some - lambda action names to match action names in std. - - API addition: - * sigc++/adaptors/retype.h.m4: New file adding - adaptor retype. - * sigc++/Makefile.am: Build and distribute new file. - * tests/test_retype.cc: New file testing adaptor retype. - * MSVC_Net2003/tests/test_retype/test_reytype.vcproj, - tests/Makefile.am: Build and distribute new test case. - -2003-11-01 Martin Schulze - - * MSVC_Net2003: New directory containing project - files for Visual Studio .Net 2003. - Credits to Roel Vanhout ! - -2003-11-01 Martin Schulze - - * sigc++/retype.h.m4: Use LIBSIGC_TEMPLATE_PREFIX - in explicit function template instantiations. - * sigc++/type_traits.h: Add template specialization - for arrays (T_type[N]) to disable non-working member - type_trait::instance(). - * sigc++/visit_each.h: Remove more disturbing - limit_derived_target<>::operator() overloads. - (Should have noticed earlier that they are unnecessary.) - * sigc++/adaptors/deduce_result_type.h.m4, - sigc++/adaptors/lambda/operator.h.m4, - sigc++/functors/functor_trait.h.m4, - tests/test_[bind,compose,exception_catch,hide,lambda].cc: - Completely removed support for typeof(). We don't need - it any more and it is completely non-standard! - -2003-10-30 Cedric Gustin - - * configure.ac: Added test of win32 platform. Commented - out AM_DISABLE_SHARED (DLLs are shared libraries). - * sigc++/Makefile.am: added a few LDFLAGS for win32 - DLLs. - -2003-10-30 Martin Schulze - - * sigc++/signal.h.m4: Add SigC::Signal#<>::slot(). - * sigc++/slot.h.m4: Comment out make_slot() work-around. - * sigc++/adaptors/bind.h.m4: Remove unnecessary brackets - in template argument lists. They are confusing MSVC. - * sigc++/adaptors/*.h.m4, sigc++/adaptors/lambda/*.h.m4: - Use LIBSIGC_TEMPLATE_PREFIX in explicit function - template instantiations. - * sigc++/tests/test_*.cc: - - Include where std::string is used. - - Use double instead of float. - -2003-10-27 Martin Schulze - - * sigc++/retype.h.m4: Cleanup. - * TODO: Bring it up to date. - -1.9.11: - -2003-10-26 Martin Schulze - - * configure.ac: Bump version number to 1.9.11. - * NEWS: Add ChangeLog summary for version 1.9.11. - -2003-10-26 Martin Schulze - - Compatiblity module: - * sigc++/signal.h.m4: Move definition of compatiblity - classes SigC::SignalN to here. - * sigc++/connection.h: - - Add connection::connected(). - - Add compatibility typedef SigC::Connection. - * sigc++/bind.h, sigc++/bind_return.h, - sigc++/class_slot.h.m4, sigc++/hide.h.m4, - sigc++/method_slot.h.m4, sigc++/object.h, - sigc++/object_slot.h.m4, sigc++/retype.h.m4, - sigc++/retype_return.h sigc++/slot.h.m4, - sigc++/compatibility.h: - New files to complete compatibility module. - Split content of compatibility.h.m4 among the new files. - * sigc++/compatibility.h.m4: Removed. - * Makefile.am: Build and distribute new files. - * tests/test_compatibility.cc: Test new stuff. - - Fixes: - * sigc++/functors/slot.h.m4: Fix copy constructor and - operator=() of slot template. - * sigc++/adaptors/bind.h.m4: Fix deduce_result_type - template specializations. bind<0>() probably compiles - with gcc-3.3, now. - -2003-10-26 Martin Schulze - - Fixes: - * sigc++/functors/slot.{cc,h.m4}: - - Fix notification process: don't defer detaching of a - slot from all referred trackables during signal emission! - - Size optimization: replace virtual functions from - struct typed_slot_rep with function pointers in slot_rep - (reduces size of a typical typed_slot_rep instantiation - by 30% !!!). - * tests/test_slot.cc: Test sigc::slot more thoroughly. - * sigc++/functors/mem_fun.h.m4: Fix visit_each(). - * sigc++/adaptos/bind_return.h.m4: Add support for - sigc::ref(). - * tests/test_bind_return.cc: Use sigc::ref(). - * sigc++/signal.h.m4: Avoid compiler warning about - uninitialized variable r_ in emit(). - * sigc++/visit_each.h: Cleanup. - - API additions: - * sigc++/adpators/lambda/operators.h.m4: Add - lambda actions sigc::{reinterpret,static,dynamic}_cast_ - to support explicit parameter conversion. - * tests/test_lambda.cc: Test sigc::static_cast_. - * sigc++/adaptors/retype_return.h.m4: New file adding - adaptor retype_return (and hide_return). - * sigc++/Makefile.am: Build and distribute new file. - * tests/test_retype_return.cc: New file testing - adaptor retype_return (and hide_return). - * tests/Makefile.am: Build and distribute new test case. - -2003-10-25 Martin Schulze - - * sigc++/visit_each.h: Remove disturbing - limit_derived_target<>::operator() overloads. - * sigc++/adaptors/bind.h.m4: Add support for sigc::ref(). - * tests/test_bind.cc: Test sigc::ref(). - * sigc++/adaptors/lambda/{operator,group,base}.h.m4: - - Move support for sigc::ref() from lambda_core<> into - lambda operator and lambda group creator functions. - - Add missing visit_each() overload for lambda<> template. - * tests/test_lambda.cc: Test auto-disconnection. - TODO: Fix a strange bug that leads to "Bus error" - during auto-disconnection. - -1.9.10: - -2003-10-23 Martin Schulze - - * configure.ac: Bump version number to 1.9.10. - * NEWS: Add ChangeLog summary for version 1.9.10. - -2003-10-23 Martin Schulze - - * sigc++/functors/{functor_trait,slot}.h.m4: - Move definition of struct nil into functor_trait.h. - -2003-10-23 Martin Schulze - - * configure.ac: Disable typeof() compiler checks. - * sigc++/adaptors/bind.h.m4: Remove unnecessary - deduce_result_type<> template specializations. - -2003-10-20 Martin Schulze - - * sigc++/adaptors/compose.h.m4: - Correct order of typedefs for good. (Patch from Jeff Franks.) - -1.9.9: - -2003-10-20 Martin Schulze - - * sigc++/connection.h: Add constructor that takes - a sigc::slot_base& to support 3rd-party slot lists - like they are used in glibmm/gtkmm. - * sigc++/functors/slot.h.m4: Make sigc::slot::call_type public. - (Fixes compile problems reported by Jeff Franks.) - * sig++/type_traits.h: Don't use long long in - sigc::is_base_and_derived. - (Fixes compile problems reported by Jeff Franks.) - * sigc++/adaptors/{bind,compose,hide,exception_catch}.h.m4: - Correct order of typedefs. (Repoted by Jeff Franks.) - * configure.ac: Bump version number to 1.9.9. - * NEWS: Add ChangeLog summary for version 1.9.9. - -1.9.8: - -2003-10-19 Martin Schulze - - * sigc++/functors/slot.h.m4: Define doxygen group functors. - * configure.ac: Bump version number to 1.9.8. - * NEWS: Add ChangeLog summary for version 1.9.8. - -2003-10-19 Martin Schulze - - * NEWS: Add announces of versions 1.9.6 and 1.9.7. - * sigc++/compatibility.h.m4: New file. Defines namespace SigC. - namespace SigC should be API compatible to libsigc++-1.2. - * sigc++/Makefile.am: Build compatibility.h. - * tests/test_compatibility.cc, tests/Makefile.am: - Add test case for compatibility module. - * docs/index.html: Change group names. - * sigc++/sigc++.h: Include connection.h. - * sigc++/connection.{cc,h}: - - Rename dependency to destroy_notify_callback. - - Change parameter name in set_slot() from d to data. - - Fix operator=(): Add "return *this;" - - Get rid of namespace functor. - - Corrections in documentation. - * sigc++/signal.{cc,h.m4}: - - Add reference counter to signal_impl. Replaces "bool destroy_". - - Move signal_base, slot_iterator[_buf], slot_list out of - namespace internal. They are part of the public API. - - Add convenience function signal#::make_slot(). - - Get rid of namespace functor. - - Corrections in documentation. - * sigc++/trackable.{cc,h}: - - Rename dependency to destroy_notify_callback. - - Rename trackable::clear() to trackable::notify_callbacks(). - - Corrections in documentation. - * sigc++/type_traits.h: Add documentation. - * sigc++/visit_each.h: - - Get rid of namespace functor. - - Add documentation. - * sigc++/adaptors[/lambda]/*: Get rid of namespace functor. - * sigc++/functors/{functor_trait.h,ptr_fun.h.m4,mem_fun.h.m4}: - - Get rid of namespace functor. - - Corrections in documentation / add documentation. - * sigc++/functors/slot.{cc,h.m4}: - - Move slot_base out of namespace internal. It's public API. - - Get rid of one-letter-parameter-names. - - Get rid of namespace functor. - - Corrections in documentation. - * tests/*.cc: Get rid of "using namespace ...". - -2003-09-10 Martin Schulze - - * sigc++/adaptors/lambda/{base,operators}.h.m4: - Add subscript ([]) and assign (=) operator. I think there are now - enough operators available to make any future power user happy. - The only one missing is the comma operator and if we added it - the logical consequence would be to also add if(), switch(), do(), - etc. lambda expressions which are really out of place in libsigc++. - * sigc++/type_traits.h: Fix is_base_and_derived<> for const types. - * tests/test_lambda.cc: Test new operators. - -1.9.7: - -2003-09-05 Martin Schulze - - * configure.ac: Bump version number to 1.9.7. - -2003-09-03 Martin Schulze - - * sigc++/adaptors/lambda/operator.h.m4: - - Restructure so that the size of the generated source file stays - reasonable for 34 operators: There are only two lambda templates - lambda_operator and lambda_operator_unary. The action is an additional - template parameter. A small template lambda_action[_unary] is specialized - for all actions. - - Add most operators that boost::lambda supports. Missing operators are - "=", "[]", "," and support for pointer arithmetic. I don't know if it's - worth adding these. In libsigc++, the purpose of lambda operators is to - provide some extra functionality for the group adaptor. - * tests/test_lambda.cc: - Test pre-increment, address and dereference operator. - -2003-08-31 Martin Schulze - - * sigc++/reference_wrapper.h, sigc++/type_traits.h, sigc++/Makefile.am: - New file reference_wrapper.h provides ref() to specify that adaptors/lambdas - should take a reference to the object passed into ref() instead of a copy. - * tests/test_lambda.cc: - - Test group() with mem_fun(). - - Use ref() where lambdas should store references to objects. - - Test var() and constant(). - * sigc++/adaptors/lambda/base.h.m4: - - Support ref() in return type deduction. - - Add var() and constant() which create lambdas for usage with lambda operators. - * sigc++/adaptors/lambda/operator.h.m4: - - Fix return type deduction. - - Remove operator{+,-,*,...} overloads added on 2003-08-29. ref() is way cleaner. - * sigc++/adaptors/lambda/group.h.m4, - sigc++/adaptors/bind.h.m4, sigc++/adaptors/compose.h.m4, - sigc++/adaptors/exception_catch.h.m4, sigc++/adaptors/hide.h.m4: - Fix return type deduction. - -2003-08-29 Martin Schulze - - * tests/test_lambda.cc: Add more tests. - * sigc++/adaptors/lambda/select.h.m4, sigc++/adaptors/lambda/lambda.cc.m4: - Make _1, _2, ... constant. - * sigc++/adaptors/lambda/operator.h.m4: - Add operator{+,-,*,...} overloads to distinguish between const and non-const objects. - Store references to non-const objects rather than copies. - This allows expressions like e.g. std::cout << _1. - * sigc++/adaptors/lambda/base.h.m4, sigc++/adaptors/lambda/group.h.m4: - Remove void specializations. Functors returning void are tested and work fine. - -2003-08-27 Martin Schulze - - * tests/test_callof.cc, tests/test_deduce_result_type.cc: - Rename, correct and improve this test case. - * tests/Makefile.am: Build and run test_deduce_result_type - instead of test_callof. - -2003-08-27 Martin Schulze - - * Update TODO. - -2003-08-27 Martin Schulze - - * sigc++/adaptors/hide.h.m4: Remove usage of callof_ignore_arg<>. - * sigc++/callof.h.m4, sigc++/adaptors/deduce_result_type.h.m4, - sigc++/functors/functor_trait.h.m4: - Remove the first and move deduce_result_type templates from - functor_trait.h.m4 into new file deduce_result_type.h.m4. - * sigc++/Makefile.am, sigc++/sigc++.h, sigc++/adaptors/adaptor_trait.h.m4: - Build and include sigc++/adaptors/deduce_result_type.h instead of callof.h. - * sigc++/functors/slot.h.m4: Document struct nil. - -2003-08-24 Martin Schulze - - * sigc++/functors/functor_trait.h.m4: Simplify usage of convenience - macro SIGC_FUNCTORS_HAVE_RESULT_TYPE: - namespace sigc{ namespace functor{ SIGC_FUNCTORS_HAVE_RESULT_TYPE }} - -2003-08-24 Martin Schulze - - * sigc++/functors/functor_trait.h,m4, sigc++/adaptors[/lambda]/*.h.m4: - Merge adaptor return type deduction and typeof() into - sigc::functor::deduce_result_type. Use it for all adaptors. - * tests/test_compose.cc: Only test multi-type get-functor if - typeof() if supported. - -2003-08-24 Martin Schulze - - * sigc++/adaptors[/lambda]/*.h.m4: - - Remove unnecessary void specializations. In fact, only the one - for sigc::functor::exception_catch<> is needed and I don't really - understand why. For the lambda stuff the void specializatoins are - just commented out at the moment. - - Make typeof() optional. Surprisingly, I got the lambda stuff working - without typeof()! The test suite doesn't catch all cases yet, so maybe - some thing are still not working. - TODO: Implement configure check. - * tests/test_bind.cc, tests/test_compose.cc tests/test_exception_catch.cc, - tests/test_hide.cc, tests/test_lambda.cc: - Only test multiple functor return types if typeof() is supported. - -2003-08-06 Martin Schulze - - * sigc++/trackable.{cc,h}: Add function trackable::clear(). - -2003-06-24 Andreas Rottmann - - * TODO: Minor tweaks. - -2003-06-23 Andreas Rottmann - - * docs/reference/Doxyfile.in: Use these variables. - * docs/reference/Makefile.am (html/index.html): Provide doxygen - with SRCDIR and TOP_SRCDIR environment variables. - - * sigc++/functors/slot.h.m4: Make slot::call_type typedef public; - this fixes a g++ 3.3 error in signal.h. - - * sigc++/signal.h.m4: Make the signal::accumulated class public; - this fixes a g++ 3.3 error in test_accumulated.cc. - -2003-06-15 Martin Schulze - - * sigc++/functor/slot.h.m4: Correct typing error in docs. - * sigc++/functor/ptr_fun.h.m4: Document the whole thing. - -2003-05-31 Murray Cumming - - * Reference documentation: Rearranged the groups to make it all - a bit more like the libsigc++ 1.2 reference documentation. - Corrected some spelling and grammar too. - This needs a lot of work. The text is very hard to read and it's - generally not appropriate for a user of the code who doesn't - care about the internals. But it's not impossible - our examples - should show us what we need to say in the documentation. - We probably need some more groups for the extra stuff, like we do - in libsigc++ 1.2. - -2003-05-29 Martin Schulze - - * sigc++/signal.h.m4: Fix documentation. - * sigc++/connection.h, sigc++/functor/slot.h.m4: - Document the whole thing. - -2003-05-29 Martin Schulze - - * sigc++/signal.h.m4: - - Remove bogus operator() from unnumbered signal<> and - signal<>::accumulated templates. - - Document the whole thing. - - * docs/index.html: Fix some links. - -2003-04-06 Martin Schulze - - * TODO, configure.ac, Makefile.am, docs/*: - Add Doxygen framework. - -2003-04-06 Martin Schulze - - * sigc++/callof.h.m4, sigc++/adaptors/*, tests/test_callof.cc: - Move sigc::callof<> to sigc::functor::internal::callof<>. - - * sigc++/functors/mem_fun.h.m4, tests/test_mem_fun.cc: - Add new types [bound_][const_]volatile_mem_functor, visit_each() - and mem_fun() overloads for volatile qualifier. - Add ctor overloads in bound_*mem_functor and mem_fun() overloads - that take reference instead of pointer. - -2003-03-26 Martin Schulze - - * Change "closure" to "slot" throughout sigc++2 (file names, - class names, member variables, documentation, etc.). - -2003-03-26 Martin Schulze - - * TODO: Rewrite to reflect recent changes as well as recent discussions. - -2003-03-24 Martin Schulze - - * sigc++/adaptors/bind_return.h.m4: Make the adaptor's data member - public so that visit_each() can access it. - - * sigc++/adaptors/lambda/*.h.m4: More fixes. Add a note about - malfunctioning typeof() (probably compiler bug in gcc-3.2). - - * tests/*.cc: Test references. Fix compose equivalent in test_lambda. - -2003-03-24 Martin Schulze - - * sigc++/Makefile.am, sigc++/functors/functor_trait.h[.m4], - sigc++/adaptors/adaptor_trait.h.m4: Move detection of function - and member method pointers' return types from adaptor_trait into - functor_trait. (We'll use functor_trait rather than adaptor_trait for - our lambda stuff.) functor_trait.h needs to be generated from .m4 now. - - * sigc++/functors/functor_trait.h.m4: Add convenience macros: - - SIGC_FUNCTORS_HAVE_RESULT_TYPE indicates that the existance of - T_functor::result_type should be assumed for all unknown functors. - - SIGC_FUNCTOR_TRAIT(T_functor, T_result) explicitly specifies the - result type of a functor. - ("typename functor_trait::result_type") is used to - determine the return type of our adaptors' operator()() overloads. - - * sigc++/adaptors/[lambda/]*.h.m4: Various fixes in visit_each() and - operator()() overloads to make these operator()() overloads usable. - Most of them were just commented out before. Some adaptor types also - have void specializations, now. - - * sigc++/adaptors/lambda/group.h.m4: Change syntax from - "[some_functor] % grp([args])" to "group([some_functor], [args])" - like we agreed on the ml some time ago. - - * sigc++/tests/test_[all adaptors].cc: Test stuff that didn't work - before. - -2003-03-22 Murray Cumming - - * Added pgk-config file, from a mystery person in bug #108857 - -2003-03-22 Martin Schulze - - * tests/test_bind.cc: Test and show how to use functor_trait - for user defined or 3rd-party functors so that a - bind<0>([functor],[arg1])() call with no arguments can return a value. - -2003-03-20 Martin Schulze - - * sigc++/callof.h.m4: Add explanations. Comment in / create templates - callof_safe[#]. Unfortunately they don't work for functors with overloaded - operator() so we don't use it for now. At least everything is documented. - - * sigc++/functors/functor_trait.h, sigc++/functors/*.h.m4: Add back - functor_base compiler hint. We're using it now in adaptor_functor<>. - - * sigc++/adaptors/{adaptor_trait,bind}.h.m4: Make operator() overloads - with no arguments return the result of the functor invocation. - Fix multiple bind<0>(). - * tests/test_bind.cc: Test the stuff that's working now. - -2003-03-16 Murray Cumming - - * Added sigc++/sigc++.h, like in libsigc++ 1.2 - * examples: Added member_method example, which uses a class method - and which demonstrates disconnection. - -1.9.6: - -2003-03-11 Andreas Rottmann - - * sigc++/Makefile.am: Use substitution references instead of - $(patsubst). Is shorter and fixes the strange-dirs-in-dist-tarball - bug. - -2003-03-09 Martin Schulze - - * sigc++/connection.h: Add block() capability. - -2003-03-09 Martin Schulze - - * sigc++/signal.{cc,h.m4}: Add flag signal_impl::destroy_ - and function signal_impl::destroy(). Use them to defer - the destruction of the signal_impl object during signal - emission. - - * tests/test_disconnect.cc: Add tests for the connection - class and for deleting signals during emission. - -2003-03-09 Martin Schulze - - * sigc++/connection.{cc,h}, sigc++/Makefile.am: - - New files that add a connection class. Objects of this - class are constructed from closure list iterators and can - be used to disconnect the refered closure. As opposed to - iterators they stay valid beyond the lifetime of the closure. - -2003-03-09 Martin Schulze - - * sigc++/functors/closure.{cc,h.m4}, sigc++/signal.cc: - - Rename closure_{base,rep}::[set_]dependency_ -> [set_]parent_. - - Make closure_rep inherit trackable. This allows for - connection objects that stay valid beyond the life time - of the refered closure. - - Make some one-line-functions inline again. - -2003-03-08 Martin Schulze - - * sigc++/trackable.cc: BUGFIX in trackable_dep_list::clear() - -2003-03-08 Andreas Rottmann - - * sigc++/Makefile.am: Rewritten so we can build lambda cleanly. - * sigc++/Makefile.am_fragment: Removed. - - * sigc++/functors/Makfile.am: Removed. - * sigc++/adaptors/Makefile.am: Removed. - * sigc++/adaptors/lambda/Makefile.am: Removed. - * configure.ac (AC_OUTPUT): Remove the above Makefiles. - - * tests/Makefile.am: Re-included lambda test. - -2003-03-07 Martin Schulze - - * sigc++/signal.{cc,h.m4}: - - signal_emit#<>: New templates replacing signal#<>::caller. - The purpose of these templates is implementing the emit - function and optimizing signal emission for the case that - no accumulator is used via template specializations. - - default_accumulator<>: Removed. The default for T_accumulator - in signal#<> now is nil. An example how to use accumulators - is available in tests/test_accumulator.cc. - - signal_{base,impl}: Move the implementation of signal_base's - interface to signal_impl. An object of this class is - dynamically allocated when first connecting a closure to - the signal. This drastically reduces the size of empty signals - and allows for future addition of a reference counter to make - it safe to delete a signal during emission. - - Directly work on closure_rep during signal emission. This - seems to be quicker than using the closure templates. - - Document the classes. Restructure the header file a bit. - - * sigc++/functors/closure.h.m4: Make closure_base::rep_ data - member public, so that signal emission can directly work on it. - - * tests/test_size.cc: Add an entry for signal_impl. - -2003-03-07 Martin Schulze - - * sigc++/functors/closure.{cc,h.m4}: - - closure_base: BUGFIXES in ~closure_base() and operator=(). - - Mark some functions with the inline keyword. This seems to - help gcc 3.2 to optimize signal emission and (dis)connection. - - Document the classes. Restructure the header file a bit. - -2003-03-07 Martin Schulze - - * sigc++/trackable.{cc,h}: Make trackable allocate a - trackable_dep_list object dynamically when adding the first - dependency. (This reduces the size of objects, that are not - refered by a closure by 4 bytes (50%) and increases the size - of objects that are refered by a closure by 4 bytes (50%) - on a 32 bit architecture => This reduces total memory use - when >50% of the trackables are not refered by a closure.) - Document the classes. - -2003-03-05 Martin Schulze - - * tests/Makefile.am, tests/test_size.cc, tests/test_accumulated.cc: - Add two test cases. test_size is showing the size of public and - internal structures. (Which apart from empty signals are smaller - than the sizes of the equivalent libsigc++-1.2 structures.) - test_accumulated is a test for the template signal<>::accumulated<> - at the same time showing the use of accumulators in libsigc++2. - - * Offtopic: My note about binary sizes from 2003-02-10 is wrong. - Stripped libsigc++2 test binaries are about 8-10k in size. - -2003-03-05 Martin Schulze - - * sigc++/visit_each.h: BUGFIX in template specialization - limit_derive_target::with_type: - Add non-const overloads for static void execute_() avoiding - compile time errors. - -2003-02-16 Martin Schulze - - * tests/Makefile.am, tests/test_disconnect.cc: - Add testcase with a mixed connection & disconnection sequence. - -2003-02-16 Martin Schulze - - * sigc++/signal.cc: Bugfix in signal_base::insert(): - Set notification function in the newly created copy of - slot_ rather than in slot_ itself. - -2003-02-10 Martin Schulze - - * sigc++/signal.h.m4: Comment in typedefs for iterator types in - the signal#<> class template. Make signal#<>::connect() return an - iterator for convenience. - (Note that the first change increases the binary size of - tests/test_signal from 201k to 204k, the second change to 206k.) - -2003-01-23 Murray Cumming - - * sigc++/adaptors/lambda is disable temporarily (not built and - not distributed) because it gets built before its parent - directory, but #includes generated sources in the parent directory. - -2003-01-22 Murray Cumming - - * Added Andreas Rottman's example. - -2003-01-22 Murray Cumming - - * Applied Andreas Rottman's make dist fixes. - -2003-01-14 Murray Cumming - - * Added whitespace to make the code more readable. diff --git a/MSVC_NMake/MSVC-Builds.md b/MSVC_NMake/MSVC-Builds.md new file mode 100644 index 00000000..777bb5ea --- /dev/null +++ b/MSVC_NMake/MSVC-Builds.md @@ -0,0 +1,78 @@ +Instructions for building libsigc++ on Visual Studio += + +Building libsigc++ on Windows is now supported using Visual Studio +versions 2017 or later in both 32-bit and 64-bit (x64 and ARM64) flavors, +via NMake Makefiles, Meson or CMake. Due to `C++17` usage, Visual Studio 2015 or +earlier is not supported, and any use of the headers installed with +this package will require the use of the `/std:c++17` compiler flag. + +libsigc++ itself has no external dependencies, but building the +benchmark test program will require an installation of the Boost +C++ libraries. + +Building with NMake +- +The following describes what items are built with the following +targets: + +* `all`, `examples`: (or no target specified): The libsigc++ DLL and the example programs. +* `tests`: The libsigc++ DLL and the test programs. +* `benchmark`: The libsigc++ DLL and the benchmark program, the Boost C++ headers should be found in one of the paths that are in`%INCLUDE%`. + +Building directly from a GIT checkout is now supported, provided that a `PERL` +installation is present (pass the `PERL` interpreter executable in your NMake +command line by using `nmake /f Makefile.vc ... PERL=` by using +the `prep-git-build` target. + +The following are instructions for performing such a build. A `clean` target is +provided-it is recommended that one cleans the build and redo the build if any +configuration option changed. An `install` target is also provided to copy the built +items in their appropriate +locations under `$(PREFIX)`, which is described below. + +Invoke the build by issuing the command: +`nmake /f Makefile.vc CFG=[release|debug] [PREFIX=...] ` +where: + +* `CFG`: Required. Choose from a `release` or `debug` build. Note that + all builds generate a `.pdb` file for each `.dll` and `.exe` built. + +* `PREFIX`: Optional. Base directory of where the third-party headers, libraries +and needed tools can be found, i.e. headers in `$(PREFIX)\include`, +libraries in `$(PREFIX)\lib` and tools and DLLs in `$(PREFIX)\bin`. If not +specified, `$(PREFIX)` is set as `$(srcroot)\..\vs$(X)\$(platform)`, where +`$(platform)` is `win32` for 32-bit builds or `x64` for 64-bit (Intel/AMD) +builds or `arm64` for 64-bit (ARM) builds, and `$(X)` is the short version of the +Visual Studio used, as follows: + * 2017: `15` + * 2019: `16` + * 2022: `17` + +* `USE_COMPAT_LIBS`: Build the libsigc++ DLL and .lib with the filename +`sigc-vc150(d)-3_0` for all builds. This is for compatibility reasons, +if re-building dependent code is not convenient, for instance + +* Options, set by `
-
-
- -libsigc++ mailing list - | -website source - | - -*SOURCEFORGE* -  - - -
- - diff --git a/docs/website/fragments/html_declaration.html_fragment b/docs/website/fragments/html_declaration.html_fragment deleted file mode 100644 index bc2e4836..00000000 --- a/docs/website/fragments/html_declaration.html_fragment +++ /dev/null @@ -1,47 +0,0 @@ - - - - - libsigc++ -- The Typesafe Callback Framework for C++ - - - - - -
- -
- - Main
- - Features
- - License
-
- Documentation
- - Download
-
- Mailing List
- - Patches
- - Git
-
- Links
- -
- -
- -
- - - - - -
libsigc++ - Callback Framework for C++ -
- -
diff --git a/docs/website/glossary.shtml b/docs/website/glossary.shtml deleted file mode 100644 index 51e8540b..00000000 --- a/docs/website/glossary.shtml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - -

Glossary of Terms

- -

adaptor (noun) - A function which alters a slot’s -signature.

- -

bind (verb) - To fix a value of a callback's argument in the -STL sense.

- -

call (verb) - The process of invoking a callback or slot.

- -

callback (noun) - A function or a member function which will -be called when a signal is emitted. A slot specifies the callback and any extra -data, such as the object instance, and extra parameters.

- -

connect (verb) - The process of specifying the callback -which will be called when the signal is emitted.

- -

emit (verb) - When a signal is emitted, the connected slots -will be called.

- -

factory (noun) - A function which takes a set of arguments and -produces a different object based on those arguments.

- -

handle (noun) - A safe version of a pointer.

- -

marshaller (noun) - When a signal has a return value, and -several slots are connected to that signal, each one returning a value, then a -marshaller chooses one single return value.

- -

safe (adj) - Any structure which falls back into uninitalized state -when its related resources are destroyed. Safe resources can be -held throughout the program. Unsafe resources may point to freed -memory.

- -

signal (noun) - An object to which callback slots can be -connected. When the signal is emitted, each callback will be invoked. The -signal and the connected slots have a specific return type and parameter types. -

- -

signal handler (noun) - Another name for a callback.

- -

signature (noun) - The return type of a function together with -the argument types of that function.

- -

slot (noun) - A safe version of a callback.

- - - - diff --git a/docs/website/index.shtml b/docs/website/index.shtml deleted file mode 100644 index c8ca9d73..00000000 --- a/docs/website/index.shtml +++ /dev/null @@ -1,87 +0,0 @@ - - - - - -

About

-

-libsigc++ implements a typesafe callback system for standard C++. It -allows you to define signals and to connect those signals to any -callback function, either global or a member function, regardless of -whether it is static or virtual. -

-

-It also contains adaptor classes for connection of dissimilar -callbacks and has an ease of use unmatched by other -C++ callback libraries. Libsigc++ is licensed under -the GNU Library General Public License, LGPL. -

-

-

Features

-
    -
  • Compile time typesafe callbacks (faster than run time checks)
  • -
  • Typesafety violations report line number correctly with - template names (no tracing template failures into headers)
  • -
  • No compiler extensions or meta compilers required
  • -
  • Proper handling of dynamic objects and signals - (deleted objects will not cause seg faults)
  • -
  • Extendable API at any level: - signal, slot, connection and trackable
  • -
  • Extensions do not require alteration of basic components
  • -
  • User definable accumulators
  • -
  • A variety of adaptors to change the callback signature: - bind, hide, retype, compose
  • -
  • Most C++ compilers can be used. libsigc++ version 2.5.1 and later require - a compiler with C++11 support
  • -
-

-

-

News

- -libsigc++ has reached the major version 2.0. -libsigc++ 2.0 has been rewritten from scratch adapting modern C++ coding techniques that -allow for a flexible and powerful but yet simple-to-use API. - -In particular the API improvements from libsigc++ 1.2 to 2.0 include: -
    -
  • Provides unnumbered signal and slot templates.
  • -
  • Supports arbitrary functor types.
  • -
  • Supports implicit argument type conversions on signal emission.
  • -
  • Adds support for overloaded functions.
  • -
  • Borrows powerful accumulator interface from boost::signal.
  • -
  • Simplifies use of adaptors like sigc::hide(): argument types need - not be specified any more (except for sigc::retype_return()).
  • -
  • More powerful adaptors: position of arguments to hide or bind can - be chosen freely; up to 7 arguments can be bound at a time.
  • -
  • Adds two useful adaptors: sigc::compose(), sigc::exception_catch().
  • -
  • Performs only one indirect function call during slot invokation - regardless of the number of adaptors used; the direct function - calls involved are inline and can be optimized away by the compiler.
  • -
  • Conforms to the STL naming scheme: only uses small letters.
  • -
  • libsigc++ 2.0 until 2.4.x supported a sigc::group() adaptor and - lambda functions. This support is discontinued in later releases, because - lambdas are supported by standard C++11.
  • -
-

- -

-Also good to check out are the Erik Thiele and Andreas Rottmann sites which -include some interesting libsigc++ tools like cross-thread support. -

- -

-

Developers

-The original library was composed by Tero Pulkkinen for the -gtkmm system, a C++ wrapper for the Gtk+ widget set. The revised -library was written and mantained by Karl Nelson. Special thanks -to Esa Pulkkinen for development tips. -The 1.2 phase was maintained by Murray Cumming after Karl provided the initial 1.2 code. -A long 1.9 phase led to the major release 2.0 which was previously maintained by Martin Schulze -and is currently being maintained by Murray Cumming and Kjell Ahlstedt. -

- - - - diff --git a/docs/website/license.shtml b/docs/website/license.shtml deleted file mode 100644 index 788b4ba0..00000000 --- a/docs/website/license.shtml +++ /dev/null @@ -1,510 +0,0 @@ - - - - - - -

-Libsigc++ is licensed under the GNU Library General Public License -for all platforms. Our intent in licensing it in this way is to -provide it for use through shared libraries in all projects both -open and proprietary. Other GNU projects may of course integrate -and link in a static manner. The full body of the license is -provided for your inspection. -

- -

-This is the only license which grants you use of the software, so -if you do not agree to its terms, you may not use this software. -

- -

-


- -
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-		       Version 2, June 1991
-
- Copyright (C) 1991 Free Software Foundation, Inc.
-                    675 Mass Ave, Cambridge, MA 02139, USA
- Everyone is permitted to copy and distribute verbatim copies
- of this license document, but changing it is not allowed.
-
-[This is the first released version of the library GPL.  It is
- numbered 2 because it goes with version 2 of the ordinary GPL.]
-
-			    Preamble
-
-  The licenses for most software are designed to take away your
-freedom to share and change it.  By contrast, the GNU General Public
-Licenses are intended to guarantee your freedom to share and change
-free software--to make sure the software is free for all its users.
-
-  This license, the Library General Public License, applies to some
-specially designated Free Software Foundation software, and to any
-other libraries whose authors decide to use it.  You can use it for
-your libraries, too.
-
-  When we speak of free software, we are referring to freedom, not
-price.  Our General Public Licenses are designed to make sure that you
-have the freedom to distribute copies of free software (and charge for
-this service if you wish), that you receive source code or can get it
-if you want it, that you can change the software or use pieces of it
-in new free programs; and that you know you can do these things.
-
-  To protect your rights, we need to make restrictions that forbid
-anyone to deny you these rights or to ask you to surrender the rights.
-These restrictions translate to certain responsibilities for you if
-you distribute copies of the library, or if you modify it.
-
-  For example, if you distribute copies of the library, whether gratis
-or for a fee, you must give the recipients all the rights that we gave
-you.  You must make sure that they, too, receive or can get the source
-code.  If you link a program with the library, you must provide
-complete object files to the recipients so that they can relink them
-with the library, after making changes to the library and recompiling
-it.  And you must show them these terms so they know their rights.
-
-  Our method of protecting your rights has two steps: (1) copyright
-the library, and (2) offer you this license which gives you legal
-permission to copy, distribute and/or modify the library.
-
-  Also, for each distributor's protection, we want to make certain
-that everyone understands that there is no warranty for this free
-library.  If the library is modified by someone else and passed on, we
-want its recipients to know that what they have is not the original
-version, so that any problems introduced by others will not reflect on
-the original authors' reputations.
-
-  Finally, any free program is threatened constantly by software
-patents.  We wish to avoid the danger that companies distributing free
-software will individually obtain patent licenses, thus in effect
-transforming the program into proprietary software.  To prevent this,
-we have made it clear that any patent must be licensed for everyone's
-free use or not licensed at all.
-
-  Most GNU software, including some libraries, is covered by the ordinary
-GNU General Public License, which was designed for utility programs.  This
-license, the GNU Library General Public License, applies to certain
-designated libraries.  This license is quite different from the ordinary
-one; be sure to read it in full, and don't assume that anything in it is
-the same as in the ordinary license.
-
-  The reason we have a separate public license for some libraries is that
-they blur the distinction we usually make between modifying or adding to a
-program and simply using it.  Linking a program with a library, without
-changing the library, is in some sense simply using the library, and is
-analogous to running a utility program or application program.  However, in
-a textual and legal sense, the linked executable is a combined work, a
-derivative of the original library, and the ordinary General Public License
-treats it as such.
-
-  Because of this blurred distinction, using the ordinary General
-Public License for libraries did not effectively promote software
-sharing, because most developers did not use the libraries.  We
-concluded that weaker conditions might promote sharing better.
-
-  However, unrestricted linking of non-free programs would deprive the
-users of those programs of all benefit from the free status of the
-libraries themselves.  This Library General Public License is intended to
-permit developers of non-free programs to use free libraries, while
-preserving your freedom as a user of such programs to change the free
-libraries that are incorporated in them.  (We have not seen how to achieve
-this as regards changes in header files, but we have achieved it as regards
-changes in the actual functions of the Library.)  The hope is that this
-will lead to faster development of free libraries.
-
-  The precise terms and conditions for copying, distribution and
-modification follow.  Pay close attention to the difference between a
-"work based on the library" and a "work that uses the library".  The
-former contains code derived from the library, while the latter only
-works together with the library.
-
-  Note that it is possible for a library to be covered by the ordinary
-General Public License rather than by this special one.
-
-		  GNU LIBRARY GENERAL PUBLIC LICENSE
-   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
-
-  0. This License Agreement applies to any software library which
-contains a notice placed by the copyright holder or other authorized
-party saying it may be distributed under the terms of this Library
-General Public License (also called "this License").  Each licensee is
-addressed as "you".
-
-  A "library" means a collection of software functions and/or data
-prepared so as to be conveniently linked with application programs
-(which use some of those functions and data) to form executables.
-
-  The "Library", below, refers to any such software library or work
-which has been distributed under these terms.  A "work based on the
-Library" means either the Library or any derivative work under
-copyright law: that is to say, a work containing the Library or a
-portion of it, either verbatim or with modifications and/or translated
-straightforwardly into another language.  (Hereinafter, translation is
-included without limitation in the term "modification".)
-
-  "Source code" for a work means the preferred form of the work for
-making modifications to it.  For a library, complete source code means
-all the source code for all modules it contains, plus any associated
-interface definition files, plus the scripts used to control compilation
-and installation of the library.
-
-  Activities other than copying, distribution and modification are not
-covered by this License; they are outside its scope.  The act of
-running a program using the Library is not restricted, and output from
-such a program is covered only if its contents constitute a work based
-on the Library (independent of the use of the Library in a tool for
-writing it).  Whether that is true depends on what the Library does
-and what the program that uses the Library does.
-  
-  1. You may copy and distribute verbatim copies of the Library's
-complete source code as you receive it, in any medium, provided that
-you conspicuously and appropriately publish on each copy an
-appropriate copyright notice and disclaimer of warranty; keep intact
-all the notices that refer to this License and to the absence of any
-warranty; and distribute a copy of this License along with the
-Library.
-
-  You may charge a fee for the physical act of transferring a copy,
-and you may at your option offer warranty protection in exchange for a
-fee.
-
-  2. You may modify your copy or copies of the Library or any portion
-of it, thus forming a work based on the Library, and copy and
-distribute such modifications or work under the terms of Section 1
-above, provided that you also meet all of these conditions:
-
-    a) The modified work must itself be a software library.
-
-    b) You must cause the files modified to carry prominent notices
-    stating that you changed the files and the date of any change.
-
-    c) You must cause the whole of the work to be licensed at no
-    charge to all third parties under the terms of this License.
-
-    d) If a facility in the modified Library refers to a function or a
-    table of data to be supplied by an application program that uses
-    the facility, other than as an argument passed when the facility
-    is invoked, then you must make a good faith effort to ensure that,
-    in the event an application does not supply such function or
-    table, the facility still operates, and performs whatever part of
-    its purpose remains meaningful.
-
-    (For example, a function in a library to compute square roots has
-    a purpose that is entirely well-defined independent of the
-    application.  Therefore, Subsection 2d requires that any
-    application-supplied function or table used by this function must
-    be optional: if the application does not supply it, the square
-    root function must still compute square roots.)
-
-These requirements apply to the modified work as a whole.  If
-identifiable sections of that work are not derived from the Library,
-and can be reasonably considered independent and separate works in
-themselves, then this License, and its terms, do not apply to those
-sections when you distribute them as separate works.  But when you
-distribute the same sections as part of a whole which is a work based
-on the Library, the distribution of the whole must be on the terms of
-this License, whose permissions for other licensees extend to the
-entire whole, and thus to each and every part regardless of who wrote
-it.
-
-Thus, it is not the intent of this section to claim rights or contest
-your rights to work written entirely by you; rather, the intent is to
-exercise the right to control the distribution of derivative or
-collective works based on the Library.
-
-In addition, mere aggregation of another work not based on the Library
-with the Library (or with a work based on the Library) on a volume of
-a storage or distribution medium does not bring the other work under
-the scope of this License.
-
-  3. You may opt to apply the terms of the ordinary GNU General Public
-License instead of this License to a given copy of the Library.  To do
-this, you must alter all the notices that refer to this License, so
-that they refer to the ordinary GNU General Public License, version 2,
-instead of to this License.  (If a newer version than version 2 of the
-ordinary GNU General Public License has appeared, then you can specify
-that version instead if you wish.)  Do not make any other change in
-these notices.
-
-  Once this change is made in a given copy, it is irreversible for
-that copy, so the ordinary GNU General Public License applies to all
-subsequent copies and derivative works made from that copy.
-
-  This option is useful when you wish to copy part of the code of
-the Library into a program that is not a library.
-
-  4. You may copy and distribute the Library (or a portion or
-derivative of it, under Section 2) in object code or executable form
-under the terms of Sections 1 and 2 above provided that you accompany
-it with the complete corresponding machine-readable source code, which
-must be distributed under the terms of Sections 1 and 2 above on a
-medium customarily used for software interchange.
-
-  If distribution of object code is made by offering access to copy
-from a designated place, then offering equivalent access to copy the
-source code from the same place satisfies the requirement to
-distribute the source code, even though third parties are not
-compelled to copy the source along with the object code.
-
-  5. A program that contains no derivative of any portion of the
-Library, but is designed to work with the Library by being compiled or
-linked with it, is called a "work that uses the Library".  Such a
-work, in isolation, is not a derivative work of the Library, and
-therefore falls outside the scope of this License.
-
-  However, linking a "work that uses the Library" with the Library
-creates an executable that is a derivative of the Library (because it
-contains portions of the Library), rather than a "work that uses the
-library".  The executable is therefore covered by this License.
-Section 6 states terms for distribution of such executables.
-
-  When a "work that uses the Library" uses material from a header file
-that is part of the Library, the object code for the work may be a
-derivative work of the Library even though the source code is not.
-Whether this is true is especially significant if the work can be
-linked without the Library, or if the work is itself a library.  The
-threshold for this to be true is not precisely defined by law.
-
-  If such an object file uses only numerical parameters, data
-structure layouts and accessors, and small macros and small inline
-functions (ten lines or less in length), then the use of the object
-file is unrestricted, regardless of whether it is legally a derivative
-work.  (Executables containing this object code plus portions of the
-Library will still fall under Section 6.)
-
-  Otherwise, if the work is a derivative of the Library, you may
-distribute the object code for the work under the terms of Section 6.
-Any executables containing that work also fall under Section 6,
-whether or not they are linked directly with the Library itself.
-
-  6. As an exception to the Sections above, you may also compile or
-link a "work that uses the Library" with the Library to produce a
-work containing portions of the Library, and distribute that work
-under terms of your choice, provided that the terms permit
-modification of the work for the customer's own use and reverse
-engineering for debugging such modifications.
-
-  You must give prominent notice with each copy of the work that the
-Library is used in it and that the Library and its use are covered by
-this License.  You must supply a copy of this License.  If the work
-during execution displays copyright notices, you must include the
-copyright notice for the Library among them, as well as a reference
-directing the user to the copy of this License.  Also, you must do one
-of these things:
-
-    a) Accompany the work with the complete corresponding
-    machine-readable source code for the Library including whatever
-    changes were used in the work (which must be distributed under
-    Sections 1 and 2 above); and, if the work is an executable linked
-    with the Library, with the complete machine-readable "work that
-    uses the Library", as object code and/or source code, so that the
-    user can modify the Library and then relink to produce a modified
-    executable containing the modified Library.  (It is understood
-    that the user who changes the contents of definitions files in the
-    Library will not necessarily be able to recompile the application
-    to use the modified definitions.)
-
-    b) Accompany the work with a written offer, valid for at
-    least three years, to give the same user the materials
-    specified in Subsection 6a, above, for a charge no more
-    than the cost of performing this distribution.
-
-    c) If distribution of the work is made by offering access to copy
-    from a designated place, offer equivalent access to copy the above
-    specified materials from the same place.
-
-    d) Verify that the user has already received a copy of these
-    materials or that you have already sent this user a copy.
-
-  For an executable, the required form of the "work that uses the
-Library" must include any data and utility programs needed for
-reproducing the executable from it.  However, as a special exception,
-the source code distributed need not include anything that is normally
-distributed (in either source or binary form) with the major
-components (compiler, kernel, and so on) of the operating system on
-which the executable runs, unless that component itself accompanies
-the executable.
-
-  It may happen that this requirement contradicts the license
-restrictions of other proprietary libraries that do not normally
-accompany the operating system.  Such a contradiction means you cannot
-use both them and the Library together in an executable that you
-distribute.
-
-  7. You may place library facilities that are a work based on the
-Library side-by-side in a single library together with other library
-facilities not covered by this License, and distribute such a combined
-library, provided that the separate distribution of the work based on
-the Library and of the other library facilities is otherwise
-permitted, and provided that you do these two things:
-
-    a) Accompany the combined library with a copy of the same work
-    based on the Library, uncombined with any other library
-    facilities.  This must be distributed under the terms of the
-    Sections above.
-
-    b) Give prominent notice with the combined library of the fact
-    that part of it is a work based on the Library, and explaining
-    where to find the accompanying uncombined form of the same work.
-
-  8. You may not copy, modify, sublicense, link with, or distribute
-the Library except as expressly provided under this License.  Any
-attempt otherwise to copy, modify, sublicense, link with, or
-distribute the Library is void, and will automatically terminate your
-rights under this License.  However, parties who have received copies,
-or rights, from you under this License will not have their licenses
-terminated so long as such parties remain in full compliance.
-
-  9. You are not required to accept this License, since you have not
-signed it.  However, nothing else grants you permission to modify or
-distribute the Library or its derivative works.  These actions are
-prohibited by law if you do not accept this License.  Therefore, by
-modifying or distributing the Library (or any work based on the
-Library), you indicate your acceptance of this License to do so, and
-all its terms and conditions for copying, distributing or modifying
-the Library or works based on it.
-
-  10. Each time you redistribute the Library (or any work based on the
-Library), the recipient automatically receives a license from the
-original licensor to copy, distribute, link with or modify the Library
-subject to these terms and conditions.  You may not impose any further
-restrictions on the recipients' exercise of the rights granted herein.
-You are not responsible for enforcing compliance by third parties to
-this License.
-
-  11. If, as a consequence of a court judgment or allegation of patent
-infringement or for any other reason (not limited to patent issues),
-conditions are imposed on you (whether by court order, agreement or
-otherwise) that contradict the conditions of this License, they do not
-excuse you from the conditions of this License.  If you cannot
-distribute so as to satisfy simultaneously your obligations under this
-License and any other pertinent obligations, then as a consequence you
-may not distribute the Library at all.  For example, if a patent
-license would not permit royalty-free redistribution of the Library by
-all those who receive copies directly or indirectly through you, then
-the only way you could satisfy both it and this License would be to
-refrain entirely from distribution of the Library.
-
-If any portion of this section is held invalid or unenforceable under any
-particular circumstance, the balance of the section is intended to apply,
-and the section as a whole is intended to apply in other circumstances.
-
-It is not the purpose of this section to induce you to infringe any
-patents or other property right claims or to contest validity of any
-such claims; this section has the sole purpose of protecting the
-integrity of the free software distribution system which is
-implemented by public license practices.  Many people have made
-generous contributions to the wide range of software distributed
-through that system in reliance on consistent application of that
-system; it is up to the author/donor to decide if he or she is willing
-to distribute software through any other system and a licensee cannot
-impose that choice.
-
-This section is intended to make thoroughly clear what is believed to
-be a consequence of the rest of this License.
-
-  12. If the distribution and/or use of the Library is restricted in
-certain countries either by patents or by copyrighted interfaces, the
-original copyright holder who places the Library under this License may add
-an explicit geographical distribution limitation excluding those countries,
-so that distribution is permitted only in or among countries not thus
-excluded.  In such case, this License incorporates the limitation as if
-written in the body of this License.
-
-  13. The Free Software Foundation may publish revised and/or new
-versions of the Library General Public License from time to time.
-Such new versions will be similar in spirit to the present version,
-but may differ in detail to address new problems or concerns.
-
-Each version is given a distinguishing version number.  If the Library
-specifies a version number of this License which applies to it and
-"any later version", you have the option of following the terms and
-conditions either of that version or of any later version published by
-the Free Software Foundation.  If the Library does not specify a
-license version number, you may choose any version ever published by
-the Free Software Foundation.
-
-  14. If you wish to incorporate parts of the Library into other free
-programs whose distribution conditions are incompatible with these,
-write to the author to ask for permission.  For software which is
-copyrighted by the Free Software Foundation, write to the Free
-Software Foundation; we sometimes make exceptions for this.  Our
-decision will be guided by the two goals of preserving the free status
-of all derivatives of our free software and of promoting the sharing
-and reuse of software generally.
-
-			    NO WARRANTY
-
-  15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
-PURPOSE.  THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
-LIBRARY IS WITH YOU.  SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
-
-  16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
-DAMAGES.
-
-		     END OF TERMS AND CONDITIONS
-
-     Appendix: How to Apply These Terms to Your New Libraries
-
-  If you develop a new library, and you want it to be of the greatest
-possible use to the public, we recommend making it free software that
-everyone can redistribute and change.  You can do so by permitting
-redistribution under these terms (or, alternatively, under the terms of the
-ordinary General Public License).
-
-  To apply these terms, attach the following notices to the library.  It is
-safest to attach them to the start of each source file to most effectively
-convey the exclusion of warranty; and each file should have at least the
-"copyright" line and a pointer to where the full notice is found.
-
-    
-    Copyright (C)   
-
-    This library is free software; you can redistribute it and/or
-    modify it under the terms of the GNU Library General Public
-    License as published by the Free Software Foundation; either
-    version 2 of the License, or (at your option) any later version.
-
-    This library is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
-    Library General Public License for more details.
-
-    You should have received a copy of the GNU Library General Public
-    License along with this library; if not, write to the Free
-    Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-Also add information on how to contact you by electronic and paper mail.
-
-You should also get your employer (if you work as a programmer) or your
-school, if any, to sign a "copyright disclaimer" for the library, if
-necessary.  Here is a sample; alter the names:
-
-  Yoyodyne, Inc., hereby disclaims all copyright interest in the
-  library `Frob' (a library for tweaking knobs) written by James Random Hacker.
-
-  , 1 April 1990
-  Ty Coon, President of Vice
-
-That's all there is to it!
-
-
- - - diff --git a/docs/website/link.shtml b/docs/website/link.shtml deleted file mode 100644 index 20bab8d0..00000000 --- a/docs/website/link.shtml +++ /dev/null @@ -1,46 +0,0 @@ - - - - -

GNOME Links

- -

-Libsigc++ is part of the greater GNOME code base. -

-

- -

Callback Links

- -

-There are a number of other C++ callback systems -and publications on construction of callback systems. -

-

- -

Users

- -

-Here is a list of some of the projects that use libsigc++. -(Have a project which is using libsigc++? Mail us.) -

-

- - - - diff --git a/docs/website/stable.shtml b/docs/website/stable.shtml deleted file mode 100644 index 3c548f7c..00000000 --- a/docs/website/stable.shtml +++ /dev/null @@ -1,30 +0,0 @@ - - - - -

Download

- -

Source Packages

- -

-The source packages for libsigc++ are available on the GNOME ftp site -and via the GNOME download site. -

- -

Binary Packages

- -

Whenever possible, you should use the official binary packages approved by the supplier of your operating system, such as your Linux distribution. -For instance, Ubuntu Linux, Debian Linux and Fedora Linux have official libsigc++ packages.

- -

Requirements

- -pkg-config should be used to build software that depends on libsigc++. - -

-libsigc++ is built and tested for a standards-compliant C++ compiler. Luckily, the recent versions of all major C++ compilers are now sufficiently standards-compliant. -libsigc++ version 2.5.1 and later require a C++11-compliant compiler. -

- - - - diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt new file mode 100644 index 00000000..82659938 --- /dev/null +++ b/examples/CMakeLists.txt @@ -0,0 +1,23 @@ +# Copyright 2016, The libsigc++ Development Team +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . + +function (add_sigcpp_example EXAMPLE_SOURCE_FILE) + get_filename_component (example_name ${EXAMPLE_SOURCE_FILE} NAME_WE) + add_executable (${example_name} ${EXAMPLE_SOURCE_FILE}) + target_link_libraries (${example_name} sigc-${SIGCXX_API_VERSION}) +endfunction (add_sigcpp_example) + +add_sigcpp_example (hello_world.cc) +add_sigcpp_example (member_method.cc) diff --git a/examples/Makefile.am b/examples/Makefile.am index b77cc24c..3df0fd1c 100644 --- a/examples/Makefile.am +++ b/examples/Makefile.am @@ -16,10 +16,12 @@ ## along with this library. If not, see . AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -AM_CXXFLAGS = $(SIGC_WXXFLAGS) +AM_CXXFLAGS = $(SIGC_WXXFLAGS) -DSIGCXX_DISABLE_DEPRECATED LDADD = $(top_builddir)/sigc++/libsigc-$(SIGCXX_API_VERSION).la noinst_PROGRAMS = hello_world member_method +dist_noinst_DATA = CMakeLists.txt + hello_world_SOURCES = hello_world.cc member_method_SOURCES = member_method.cc diff --git a/examples/hello_world.cc b/examples/hello_world.cc index aff82f2c..6a171abf 100644 --- a/examples/hello_world.cc +++ b/examples/hello_world.cc @@ -1,4 +1,4 @@ -/* Copyright 2003, The libsigc++ Development Team +/* Copyright 2003 - 2016, The libsigc++ Development Team * * Assigned to the public domain. Use as you wish without * restriction. @@ -9,17 +9,19 @@ #include -void on_print(const std::string& str) +void +on_print(const std::string& str) { std::cout << str; } -int main() +int +main() { - sigc::signal signal_print; - - signal_print.connect( sigc::ptr_fun(&on_print) ); - + sigc::signal signal_print; + + signal_print.connect(sigc::ptr_fun(&on_print)); + signal_print.emit("hello world\n"); return 0; diff --git a/examples/member_method.cc b/examples/member_method.cc index 574b1fc8..5fc5b2cf 100644 --- a/examples/member_method.cc +++ b/examples/member_method.cc @@ -1,4 +1,4 @@ -/* Copyright 2003, The libsigc++ Development Team +/* Copyright 2003 - 2016, The libsigc++ Development Team * * Assigned to the public domain. Use as you wish without * restriction. @@ -15,32 +15,32 @@ class Something : public sigc::trackable Something(); protected: + void on_print(int a); - virtual void on_print(int a); - - typedef sigc::signal type_signal_print; + using type_signal_print = sigc::signal; type_signal_print signal_print; - }; Something::Something() { - auto iter = signal_print.connect( sigc::mem_fun(this, &Something::on_print) ); + auto connection = signal_print.connect(sigc::mem_fun(*this, &Something::on_print)); signal_print.emit(2); - //This isn't necessary - it's just to demonstrate how to disconnect: - iter->disconnect(); - signal_print.emit(3); //Prove that it is no longer connected. + // This isn't necessary - it's just to demonstrate how to disconnect: + connection.disconnect(); + signal_print.emit(3); // Prove that it is no longer connected. } -void Something::on_print(int a) +void +Something::on_print(int a) { - std::cout << "on_print recieved: " << a << std::endl; + std::cout << "on_print received: " << a << std::endl; } -int main() +int +main() { - Something something; + Something something; return 0; } diff --git a/examples/meson.build b/examples/meson.build new file mode 100644 index 00000000..0ddf68ef --- /dev/null +++ b/examples/meson.build @@ -0,0 +1,29 @@ +# examples + +# input: sigcxx_own_dep, build_examples + +examples = [ +# [[dir-name], exe-name, [sources]] + [[], 'hello_world', ['hello_world.cc']], + [[], 'member_method', ['member_method.cc']], +] + +foreach ex : examples + dir = '' + foreach dir_part : ex[0] + dir = dir / dir_part + endforeach + ex_name = (dir / ex[1]).underscorify() + ex_sources = [] + foreach src : ex[2] + ex_sources += dir / src + endforeach + + exe_file = executable(ex_name, ex_sources, + cpp_args: '-DSIGCXX_DISABLE_DEPRECATED=1', + dependencies: sigcxx_own_dep, + implicit_include_directories: false, + build_by_default: build_examples, + install: false, + ) +endforeach diff --git a/examples/qt_with_qmake/README.md b/examples/qt_with_qmake/README.md new file mode 100644 index 00000000..e19ccf61 --- /dev/null +++ b/examples/qt_with_qmake/README.md @@ -0,0 +1,67 @@ +# libsigc++ with Qt + +It is possible to use libsigc++ with Qt. However, because of the signals/slots +mechanism of Qt, there is some setup that must be done in order for this to +happen correctly. + +The official Qt documentation may be found here: https://doc.qt.io/qt-5/signalsandslots.html#using-qt-with-3rd-party-signals-and-slots + +Steps to use libsigc++ with Qt: +1. In your .pro file, add `CONFIG += no_keywords`. This configures Qt to not +define the macros `emit`, `signals`, and `slot`. These are keywords for moc, +which preprocesses the source files in order to use Qt signals/slots. +2. In your header files, change the `signals:` section of your class to instead +be `Q_SIGNALS` +3. In your header files, change the `public slots:` section of your class to +instead be `public Q_SLOTS:` +4. In any class that you emit a signal, change `emit` to be `Q_EMIT`. + +In general, using the Q\_ macros is a good idea if your code is a library +intended to be used by people other than yourself, as they may be using +code(e.g. libsigc++/boost signals) that will conflict with Qt(moc) keywords. + +Here's an example of a class before and after this conversion(note: irrelevant +code has been removed): + +``` +class ExampleClass : public QObject { +signals: + void exampleSignal(); +public slots: + void example_slot(){ + emit exampleSignal(); + } +}; +``` + +After conversion: +``` +class ExampleClass : public QObject { +Q_SIGNALS: + void exampleSignal(); +public Q_SLOTS: + void example_slot(){ + Q_EMIT exampleSignal(); + } +}; +``` + +## Qt Slots Notes +Since libsigc++ simply requires a slot to be a function, you can call Qt +slots easily using libsigc++. Similarly, a function that is a libsigc++ slot +can also be used as a Qt slot. + +# Other Build Systems +If you are not using qmake to build your Qt project, you must tell your +buildsystem to define `QT_NO_KEYWORDS`. If you're using CMake, this may +be done like the following: + +``` +add_definitions(-DQT_NO_KEYWORDS) +``` + +or in a more modern CMake way: + +``` +target_compile_definitions(some_target PRIVATE QT_NO_KEYWORDS) +``` diff --git a/examples/qt_with_qmake/exampleclass.cpp b/examples/qt_with_qmake/exampleclass.cpp new file mode 100644 index 00000000..2d178b49 --- /dev/null +++ b/examples/qt_with_qmake/exampleclass.cpp @@ -0,0 +1,34 @@ +#include + +#include "exampleclass.h" + +ExampleClass::ExampleClass(QObject *parent) : + QObject(parent) +{ + /* Create a slot from our example_slot method. */ + m_sigc_slot = sigc::mem_fun( *this, &ExampleClass::example_slot ); + + /* Connect our sigc++ signal to our sigc++ slot */ + m_sigc_signal.connect( m_sigc_slot ); + + /* Emit a sigc++ signal */ + m_sigc_signal.emit(); + + /* Connect the Qt signal to our Qt slot */ + connect( &m_timer, &QTimer::timeout, + this, &ExampleClass::timer_slot ); + m_timer.start( 200 ); + + /* Emit a Qt signal */ + Q_EMIT example_signal(); +} + +void ExampleClass::timer_slot(){ + qDebug() << "Timer slot called"; + + QCoreApplication::exit( 0 ); +} + +void ExampleClass::example_slot(){ + qDebug() << "Example slot called"; +} diff --git a/examples/qt_with_qmake/exampleclass.h b/examples/qt_with_qmake/exampleclass.h new file mode 100644 index 00000000..7c8c5a76 --- /dev/null +++ b/examples/qt_with_qmake/exampleclass.h @@ -0,0 +1,36 @@ +#ifndef EXAMPLECLASS_H +#define EXAMPLECLASS_H + +#include +#include +#include + +#include + +class ExampleClass : public QObject +{ + Q_OBJECT +public: + explicit ExampleClass(QObject* parent = nullptr); + + /* Instead of using the keyword 'signals', use the 'Q_SIGNALS' macro */ +Q_SIGNALS: + void example_signal(); + + /* Instead of using the keyword 'slots', use the 'Q_SLOTS' macro */ +public Q_SLOTS: + void timer_slot(); + + /** + * This slot is called using libsigc++, however since it is defined under Q_SLOTS + * it could also be used with the Qt signals/slots + */ + void example_slot(); + +private: + sigc::slot m_sigc_slot; + sigc::signal m_sigc_signal; + QTimer m_timer; +}; + +#endif // EXAMPLECLASS_H diff --git a/examples/qt_with_qmake/main.cpp b/examples/qt_with_qmake/main.cpp new file mode 100644 index 00000000..c7dd7825 --- /dev/null +++ b/examples/qt_with_qmake/main.cpp @@ -0,0 +1,13 @@ +#include +#include + +#include "exampleclass.h" + +int main(int argc, char *argv[]) +{ + QCoreApplication a(argc, argv); + + ExampleClass ex; + + return a.exec(); +} diff --git a/examples/qt_with_qmake/qt-sigcpp.pro b/examples/qt_with_qmake/qt-sigcpp.pro new file mode 100644 index 00000000..154ab8f0 --- /dev/null +++ b/examples/qt_with_qmake/qt-sigcpp.pro @@ -0,0 +1,39 @@ +QT -= gui + +CONFIG += console +CONFIG -= app_bundle + +# Qt 5.12 introduces the 'c++17' config option; this sets it manually +QMAKE_CXXFLAGS += -std=c++17 + +# Since Qt #defines emit, signal, and slot, we need to disable those keywords +CONFIG += no_keywords + +# We must link with sigc++-3.0 +unix{ + CONFIG += link_pkgconfig + PKGCONFIG += sigc++-3.0 +} + +# The following define makes your compiler emit warnings if you use +# any Qt feature that has been marked deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if it uses deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + +SOURCES += \ + main.cpp \ + exampleclass.cpp + +# Default rules for deployment. +qnx: target.path = /tmp/$${TARGET}/bin +else: unix:!android: target.path = /opt/$${TARGET}/bin +!isEmpty(target.path): INSTALLS += target + +HEADERS += \ + exampleclass.h diff --git a/libsigc++2.doap b/libsigcplusplus.doap similarity index 55% rename from libsigc++2.doap rename to libsigcplusplus.doap index ac695d2c..04b52680 100644 --- a/libsigc++2.doap +++ b/libsigcplusplus.doap @@ -1,23 +1,30 @@ + + libsigc++ Typesafe callback framework for C++ - libsigc++ implements a typesafe callback system for standard C++. + +libsigc++ implements a typesafe callback system for standard C++. It allows you to define signals and to connect those signals to any callback function, either global or a member function, regardless of whether it is static or virtual. -libsigc++ is used by glibmm and gtkmm to wrap Glib and GTK+ signals. - - - +libsigc++ is also used by glibmm and gtkmm to wrap GLib and GTK signals. + + + + + + C++ - @@ -29,7 +36,7 @@ libsigc++ is used by glibmm and gtkmm to wrap Glib and GTK+ signals. Kjell Ahlstedt - + kjellahl diff --git a/meson.build b/meson.build new file mode 100644 index 00000000..4d60b1b4 --- /dev/null +++ b/meson.build @@ -0,0 +1,370 @@ +# This file is part of libsigc++. + +project('libsigc++', 'cpp', + version: '3.6.0', + license: 'LGPLv2.1+', + default_options: [ + 'cpp_std=c++17', + 'warning_level=1', + ], + meson_version: '>= 0.62.0', # required for variables in pkgconfig.generate() +) + +sigcxx_api_version = '3.0' +sigcxx_pcname = 'sigc++-' + sigcxx_api_version + +sigcxx_version_array = meson.project_version().split('.') +sigcxx_major_version = sigcxx_version_array[0].to_int() +sigcxx_minor_version = sigcxx_version_array[1].to_int() +sigcxx_micro_version = sigcxx_version_array[2].to_int() + +# http://www.gnu.org/software/libtool/manual/html_node/Updating-version-info.html +# The relation between libtool's current:revison:age interface versioning +# and the .so filename, .so.x.y.z, is +# x = current - age +# y = age +# z = revision +# If libtool_soversion is updated as described in libtool's documentation, +# x.y.z will usually *not* be equal to meson.project_version(). +libtool_soversion = [0, 0, 0] +sigcxx_libversion = '@0@.@1@.@2@'.format( + libtool_soversion[0] - libtool_soversion[2], + libtool_soversion[2], + libtool_soversion[1]) +darwin_versions = [libtool_soversion[0] + 1, '@0@.@1@'.format(libtool_soversion[0] + 1, libtool_soversion[1])] + +# Source and build root directories of the current (sub)project. +project_source_root = meson.project_source_root() +project_build_root = meson.project_build_root() + +cpp_compiler = meson.get_compiler('cpp') +cpp_compiler_id = cpp_compiler.get_id() +is_msvc_style = cpp_compiler.get_argument_syntax() == 'msvc' +python3 = find_program('python3', version: '>=3.7') + +# MSVC: We currently do not support shared and static builds at the same time, +# since we need different defines/cflags for proper linking. +if is_msvc_style + if get_option('default_library') == 'both' + error('-Ddefault_library=both is currently not supported for Visual Studio') + endif + is_msvc_static = get_option('default_library') == 'static' +else + is_msvc_static = false +endif + +# Do we build from a git repository? +# Suppose we do if and only if the meson.build file is tracked by git. +cmd_py = ''' +import shutil, subprocess, sys +git_exe = shutil.which('git') +if not git_exe: + sys.exit(1) +cmd = [ git_exe, 'ls-files', '--error-unmatch', 'meson.build' ] +sys.exit(subprocess.run(cmd, cwd=sys.argv[1], stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL).returncode) +''' +is_git_build = run_command( + python3, '-c', cmd_py, + project_source_root, + check: false, +).returncode() == 0 + +# Are we testing a dist tarball while it's being built? +# There ought to be a better way. https://github.com/mesonbuild/meson/issues/6866 +is_dist_check = project_source_root.contains('dist-unpack') and \ + project_build_root.contains('dist-build') + +# Options. +maintainer_mode_opt = get_option('maintainer-mode') +maintainer_mode = maintainer_mode_opt == 'true' or \ + (maintainer_mode_opt == 'if-git-build' and is_git_build) +if is_dist_check + message('Looks like a tarball is being tested. ' + \ + 'Option "dist-warnings" is used instead of "warnings".') + cpp_warnings = get_option('dist-warnings') +else + cpp_warnings = get_option('warnings') +endif +if get_option('warning_level') in ['0','1','2','3','4','5'] + warning_level = get_option('warning_level').to_int() +else + # For instance get_option('warning_level') == 'everything' + warning_level = 99 +endif +werror = get_option('werror') +build_deprecated_api = get_option('build-deprecated-api') +build_documentation_opt = get_option('build-documentation') +build_documentation = build_documentation_opt == 'true' or \ + (build_documentation_opt == 'if-maintainer-mode' and maintainer_mode) +build_examples = get_option('build-examples') +build_tests = get_option('build-tests') +do_benchmark = get_option('benchmark') + +# Installation directories are relative to {prefix}. +install_prefix = get_option('prefix') +install_includedir = get_option('includedir') +install_libdir = get_option('libdir') +install_datadir = get_option('datadir') +install_pkgconfigdir = install_libdir / 'pkgconfig' + +# Dependencies. +# sigcxx_build_dep: Dependencies when building the libsigc++ library. +# sigcxx_dep (created in sigc++/meson.build): +# Dependencies when using the libsigc++ library. +sigcxx_build_dep = [] # No dependencies + +benchmark_dep = dependency('boost', modules: ['system', 'timer'], + version: '>=1.20.0', required: do_benchmark) +can_benchmark = benchmark_dep.found() + +if is_msvc_style + # We must have Visual Studio 2017 15.7 or later... + mscver = cpp_compiler.get_define('_MSC_VER') + assert(mscver == '' or mscver.version_compare('>=1914'), + 'Visual Studio 2017 15.7 or later or compatible is required') +endif + +# Some dependencies are required only in maintainer mode and/or +# if documentation shall be built. +mm_common_get = find_program('mm-common-get', required: false) + +if maintainer_mode and not mm_common_get.found() + message('Maintainer mode requires the \'mm-common-get\' command. If it is not found,\n' + + 'use \'-Dmaintainer-mode=false\' or install the \'mm-common\' package, version 1.0.0 or higher.') + # If meson --wrap-mode != forcefallback, Meson falls back to the mm-common + # subproject only if mm-common-get is required. + mm_common_get = find_program('mm-common-get', required: true) +endif + +doxygen = find_program('doxygen', required: build_documentation) +dot = find_program('dot', required: false) # Used by Doxygen, if found +xsltproc = find_program('xsltproc', required: build_documentation) + +if build_documentation and not dot.found() + message('The \'dot\' command is not found.\n ' + \ + 'This will affect the look of the inheritance diagrams in the documentation.') +endif + +script_dir = project_source_root / 'untracked' / 'build_scripts' +doc_reference = script_dir / 'doc-reference.py' +dist_changelog = script_dir / 'dist-changelog.py' +dist_build_scripts = script_dir / 'dist-build-scripts.py' +tutorial_custom_cmd = project_source_root / 'tools' / 'tutorial-custom-cmd.py' + +if maintainer_mode + # Copy files to untracked/build_scripts and untracked/docs/docs. + run_command(mm_common_get, '--force', script_dir, + project_source_root / 'untracked' / 'docs' / 'docs', + check: true, + ) +elif not import('fs').is_file(doc_reference) + warning('Missing files in untracked/.\n ' + \ + 'Enable maintainer-mode if you want to build documentation or create a dist tarball.') +endif + +# Check if perl is required and available. +doc_perl_prop = run_command( + python3, doc_reference, 'get_script_property', + '', # MMDOCTOOLDIR is not used + 'requires_perl', + check: false, +) +if not (doc_perl_prop.returncode() == 0 and doc_perl_prop.stdout() == 'false') + # Perl is required, if documentation shall be built. + perl = find_program('perl', required: build_documentation) +endif + +# Set compiler warnings. +# Meson warns if any of the /W1, /W2, /W3, /W4, /Wall, -Wall, -Wextra, -Werror +# compiler options are added with add_project_arguments(). +# Avoid such warnings, when possible. +# See _warn_about_builtin_args() in meson/mesonbuild/interpreter/interpreter.py. +warning_flags = [] +if cpp_warnings == 'min' + if warning_level == 0 + warning_flags = is_msvc_style ? ['/W2'] : ['-Wall'] + endif +elif cpp_warnings == 'max' or cpp_warnings == 'fatal' + if warning_level < 3 + warning_flags = is_msvc_style ? ['/W4'] : ['-pedantic', '-Wall', '-Wextra'] + endif + if not is_msvc_style + warning_flags += '-Wsuggest-override -Wshadow -Wzero-as-null-pointer-constant -Wformat-security'.split() + endif + if cpp_warnings == 'fatal' and not werror + warning_flags += is_msvc_style ? ['/WX'] : ['-Werror'] + endif +endif + +warning_flags = cpp_compiler.get_supported_arguments(warning_flags) +add_project_arguments(warning_flags, language: 'cpp') + +# MSVC: Ignore warnings that aren't really harmful, but make those +# that should not be overlooked stand out. +static_cxxflag = '-DLIBSIGCXX_STATIC' +msvc_static_cxxflag = is_msvc_static ? static_cxxflag : '' +if is_msvc_style + disable_warnings_list = [ + '/EHsc', # avoid warnings caused by exception handling model used + ] + + # Turn off harmless warnings but make potentially dangerous ones glaring, + # distributed with GLib, if available + use_recommended_pragmas = cpp_compiler.get_supported_arguments('/FImsvc_recommended_pragmas.h') + if use_recommended_pragmas.length() > 0 + add_project_arguments(use_recommended_pragmas, language: 'cpp') + else + disable_warnings_list += '/wd4244' # 'conversion' conversion from + # 'type1' to 'type2', possible loss of data + endif + + if host_machine.cpu_family() == 'x86_64' or host_machine.cpu_family() == 'aarch64' + # 'var' : conversion from 'size_t' to 'type', possible loss of data (applies on 64-bit builds) + disable_warnings_list += '/wd4267' + endif + add_project_arguments( + cpp_compiler.get_supported_arguments(disable_warnings_list), + language: 'cpp' + ) + if is_msvc_static + add_project_arguments(static_cxxflag, language: 'cpp') + endif +endif + +# Configure files +pkg_conf_data = configuration_data() +pkg_conf_data.set('PACKAGE_VERSION', meson.project_version()) +pkg_conf_data.set('SIGCXX_API_VERSION', sigcxx_api_version) + +if not build_deprecated_api + pkg_conf_data.set('SIGCXX_DISABLE_DEPRECATED', 1) +endif +pkg_conf_data.set('SIGCXX_MAJOR_VERSION', sigcxx_major_version) +pkg_conf_data.set('SIGCXX_MINOR_VERSION', sigcxx_minor_version) +pkg_conf_data.set('SIGCXX_MICRO_VERSION', sigcxx_micro_version) + +sigcxxconfig_h_meson = files('sigc++config.h.meson') +install_includeconfigdir = install_libdir / sigcxx_pcname / 'include' +configure_file( + input: sigcxxconfig_h_meson, + output: 'sigc++config.h', + configuration: pkg_conf_data, + install: true, + install_dir: install_includeconfigdir, + install_tag: 'devel', +) + +#subdir('cmake') +subdir('MSVC_NMake') +subdir('sigc++') +subdir('examples') +subdir('tests') +subdir('docs/docs/reference') +subdir('docs/docs/manual') + +# Add a ChangeLog file to the distribution directory. +meson.add_dist_script( + python3, dist_changelog, + project_source_root, +) + +# Don't distribute these files and directories. +dont_distribute = [ + 'libsigcplusplus.doap', + '.github', +] +# Add build scripts to the distribution directory, and delete .gitignore +# files and an empty $MESON_PROJECT_DIST_ROOT/build/ directory. +meson.add_dist_script( + python3, dist_build_scripts, + project_source_root, + 'untracked' / 'build_scripts', + dont_distribute, +) + +if meson.is_subproject() + pkgconfig_vars = { + 'htmlrefdir': install_prefix / install_docdir / 'reference' / 'html', + 'htmlrefpub': 'https://libsigcplusplus.github.io/libsigcplusplus/reference/html/' + } + if build_documentation + pkgconfig_vars += {'doxytagfile': tag_file.full_path()} + # May be used in a main project. + global_tag_file_target = tag_file + endif + sigcxx_dep = declare_dependency( + dependencies: sigcxx_own_dep, + variables: pkgconfig_vars, + ) + + # A main project that looks for sigcxx_pcname.pc shall find sigcxx_dep. + meson.override_dependency(sigcxx_pcname, sigcxx_dep) +endif + +# Print a summary. +real_maintainer_mode = '' +if maintainer_mode_opt == 'if-git-build' + real_maintainer_mode = ' (@0@)'.format(maintainer_mode) +endif + +real_build_documentation = '' +if build_documentation_opt == 'if-maintainer-mode' + real_build_documentation = ' (@0@)'.format(build_documentation) +endif + +explain_man = '' +if build_manual_opt and not build_manual + explain_man = ' (requires that documentation is built)' +endif + +validate = get_option('validation') and can_parse_and_validate and build_manual +explain_val = '' +if get_option('validation') and not validate + if not build_manual + explain_val = ' (requires that the tutorial is built)' + else + explain_val = ' (requires xmllint with Relax NG and DocBook V5.0 support)' + endif +endif + +build_pdf = build_pdf_by_default and can_build_pdf and build_manual +explain_pdf = '' +if build_pdf_by_default and not build_pdf + if not build_manual + explain_pdf = ' (requires that the tutorial is built)' + else + explain_pdf = ' (requires dblatex or (xsltproc and fop))' + endif +endif + +summary = [ + '', + '------', + meson.project_name() + ' ' + meson.project_version(), + '', + ' Maintainer mode: @0@@1@'.format(maintainer_mode_opt, real_maintainer_mode), + ' Compiler warnings: @0@ (warning_level: @1@, werror: @2@)'. \ + format(cpp_warnings, warning_level, werror), + ' Build deprecated API: @0@'.format(build_deprecated_api), + 'Build HTML documentation: @0@@1@'.format(build_documentation_opt, real_build_documentation), + ' Build tutorial: @0@@1@'.format(build_manual, explain_man), + ' XML validation: @0@@1@'.format(validate, explain_val), + ' Build PDF: @0@@1@'.format(build_pdf, explain_pdf), + ' Build example programs: @0@'.format(build_examples), + ' Build test programs: @0@'.format(build_tests), + ' Benchmark: @0@'.format(do_benchmark), + 'Directories:', + ' prefix: @0@'.format(install_prefix), + ' includedir: @0@'.format(install_prefix / install_includedir), + ' includesigcxxdir: @0@'.format(install_prefix / install_includedir / sigcxx_pcname), + ' libdir: @0@'.format(install_prefix / install_libdir), + ' includeconfigdir: @0@'.format(install_prefix / install_includeconfigdir), + ' pkgconfigdir: @0@'.format(install_prefix / install_pkgconfigdir), + ' datadir: @0@'.format(install_prefix / install_datadir), + ' docdir: @0@'.format(install_prefix / install_docdir), + ' devhelpdir: @0@'.format(install_prefix / install_devhelpdir), + ' tutorialdir: @0@'.format(install_prefix / install_tutorialdir), + '------' +] + +message('\n'.join(summary)) diff --git a/meson_options.txt b/meson_options.txt new file mode 100644 index 00000000..0255a923 --- /dev/null +++ b/meson_options.txt @@ -0,0 +1,22 @@ +option('maintainer-mode', type: 'combo', choices: ['false', 'if-git-build', 'true'], + value: 'if-git-build', description: 'Let mm-common-get copy some files to untracked/') +option('warnings', type: 'combo', choices: ['no', 'min', 'max', 'fatal'], + value: 'min', description: 'Compiler warning level') +option('dist-warnings', type: 'combo', choices: ['no', 'min', 'max', 'fatal'], + value: 'fatal', description: 'Compiler warning level when a tarball is created') +option('build-deprecated-api', type: 'boolean', value: true, + description: 'Build deprecated API and include it in the library') +option('build-documentation', type: 'combo', choices: ['false', 'if-maintainer-mode', 'true'], + value: 'if-maintainer-mode', description: 'Build and install the documentation') +option('build-manual', type: 'boolean', value: true, + description: 'Build tutorial HTML files, if documentation is built') +option('validation', type: 'boolean', value: true, + description: 'Validate the tutorial XML file, if tutorial HTML files are built') +option('build-pdf', type: 'boolean', value: false, + description: 'Build tutorial PDF file, if tutorial HTML files are built') +option('build-examples', type: 'boolean', value: true, + description: 'Build example programs') +option('build-tests', type: 'boolean', value: true, + description: 'Build test programs') +option('benchmark', type: 'boolean', value: false, + description: 'Build and test benchmark program') diff --git a/sigc++-uninstalled.pc.in b/sigc++-uninstalled.pc.in index 9a9fde1a..89b2c26c 100644 --- a/sigc++-uninstalled.pc.in +++ b/sigc++-uninstalled.pc.in @@ -1,9 +1,9 @@ doxytagfile=${pc_top_builddir}/docs/reference/libsigc++-@SIGCXX_API_VERSION@.tag -htmlrefpub=http://library.gnome.org/devel/libsigc++/unstable/ +htmlrefpub=https://libsigcplusplus.github.io/libsigcplusplus/reference/html/ Name: libsigc++ Description: Typesafe signal and callback system for C++, not installed Version: @PACKAGE_VERSION@ -URL: http://libsigc.sourceforge.net/ +URL: https://libsigcplusplus.github.io/libsigcplusplus/ Libs: ${pc_top_builddir}/sigc++/libsigc-@SIGCXX_API_VERSION@.la Cflags: -I${pc_top_builddir} -I${pc_top_builddir}/@top_srcdir@ diff --git a/sigc++.pc.in b/sigc++.pc.in index c03a1ddc..e162f2fc 100644 --- a/sigc++.pc.in +++ b/sigc++.pc.in @@ -8,11 +8,11 @@ includedir=@includedir@ docdir=${datarootdir}/doc/libsigc++-@SIGCXX_API_VERSION@ doxytagfile=${docdir}/reference/libsigc++-@SIGCXX_API_VERSION@.tag htmlrefdir=${docdir}/reference/html -htmlrefpub=http://library.gnome.org/devel/libsigc++/unstable/ +htmlrefpub=https://libsigcplusplus.github.io/libsigcplusplus/reference/html/ Name: libsigc++ Description: Typesafe signal and callback system for C++ Version: @PACKAGE_VERSION@ -URL: http://libsigc.sourceforge.net/ +URL: https://libsigcplusplus.github.io/libsigcplusplus/ Libs: -L${libdir} -lsigc-@SIGCXX_API_VERSION@ -Cflags: -I${includedir}/sigc++-@SIGCXX_API_VERSION@ -I${libdir}/sigc++-@SIGCXX_API_VERSION@/include +Cflags: -I${includedir}/sigc++-@SIGCXX_API_VERSION@ -I${libdir}/sigc++-@SIGCXX_API_VERSION@/include @MSVC_STATIC_CXXFLAG@ diff --git a/sigc++/.gitignore b/sigc++/.gitignore deleted file mode 100644 index 5dc14d77..00000000 --- a/sigc++/.gitignore +++ /dev/null @@ -1,19 +0,0 @@ -/limit_reference.h -/signal.h -/adaptors/adaptor_trait.h -/adaptors/bind.h -/adaptors/bind_return.h -/adaptors/compose.h -/adaptors/deduce_result_type.h -/adaptors/exception_catch.h -/adaptors/hide.h -/adaptors/retype.h -/adaptors/retype_return.h -/adaptors/track_obj.h -/adaptors/lambda/base.h -/adaptors/lambda/lambda.cc -/adaptors/lambda/select.h -/functors/functor_trait.h -/functors/mem_fun.h -/functors/ptr_fun.h -/functors/slot.h diff --git a/sigc++/CMakeLists.txt b/sigc++/CMakeLists.txt new file mode 100644 index 00000000..d6945b2f --- /dev/null +++ b/sigc++/CMakeLists.txt @@ -0,0 +1,47 @@ +# Copyright 2016, The libsigc++ Development Team +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . + +set (SOURCE_FILES + connection.cc + scoped_connection.cc + signal_base.cc + trackable.cc + functors/slot_base.cc +) + +set (SIGCPP_LIB_NAME sigc-${SIGCXX_API_VERSION}) + +add_library(${SIGCPP_LIB_NAME} SHARED ${SOURCE_FILES}) + +set_property (TARGET ${SIGCPP_LIB_NAME} PROPERTY VERSION ${PACKAGE_VERSION}) +set_property(TARGET ${SIGCPP_LIB_NAME} PROPERTY SOVERSION ${LIBSIGCPP_SOVERSION}) +target_compile_definitions( ${SIGCPP_LIB_NAME} PRIVATE -DSIGC_BUILD ) + +set (INCLUDE_INSTALL_DIR "include/${PROJECT_NAME}-${SIGCXX_API_VERSION}") + +install ( + DIRECTORY "${PROJECT_SOURCE_DIR}" + DESTINATION "${INCLUDE_INSTALL_DIR}" + FILES_MATCHING PATTERN "*.h" +) + +set (PROJECT_CMAKE_NAME ${PROJECT_NAME}-3) + +install ( + TARGETS ${SIGCPP_LIB_NAME} + EXPORT "${PROJECT_CMAKE_NAME}Targets" + LIBRARY DESTINATION "lib" + INCLUDES DESTINATION "${INCLUDE_INSTALL_DIR}" +) diff --git a/sigc++/Makefile.am b/sigc++/Makefile.am index caa9e154..b8be4c27 100644 --- a/sigc++/Makefile.am +++ b/sigc++/Makefile.am @@ -20,23 +20,16 @@ AUTOMAKE_OPTIONS = subdir-objects include $(srcdir)/filelist.am # Subdirectories needed also in the build dir -build_subdirs = functors adaptors/lambda +build_subdirs = functors -dist_noinst_DATA = $(sigc_m4) +dist_noinst_DATA = CMakeLists.txt library_includedir = $(includedir)/$(SIGCXX_MODULE_NAME)/sigc++ nobase_library_include_HEADERS = sigc++.h $(sigc_public_h) $(sigc_built_h) lib_LTLIBRARIES = libsigc-@SIGCXX_API_VERSION@.la -libsigc_@SIGCXX_API_VERSION@_la_SOURCES = \ - signal.cc \ - signal_base.cc \ - trackable.cc \ - connection.cc \ - functors/slot.cc \ - functors/slot_base.cc \ - adaptors/lambda/lambda.cc +libsigc_@SIGCXX_API_VERSION@_la_SOURCES = $(sigc_sources_cc) EXTRA_libsigc_@SIGCXX_API_VERSION@_la_SOURCES = $(sigc_built_cc) @@ -49,8 +42,6 @@ AM_CXXFLAGS = $(SIGC_WXXFLAGS) BUILT_SOURCES = $(build_subdirs) $(sigc_built_h) $(sigc_built_cc) MAINTAINERCLEANFILES = $(sigc_built_h) $(sigc_built_cc) -m4_dir = $(srcdir)/macros - $(build_subdirs): $(AM_V_at)$(MKDIR_P) $@ @@ -62,22 +53,8 @@ signal.cc: \ functors/mem_fun.h \ functors/functor_trait.h -adaptors/lambda/lambda.cc: \ - adaptors/lambda/select.h \ - adaptors/lambda/base.h \ - adaptors/adaptor_trait.h \ - adaptors/deduce_result_type.h \ - functors/ptr_fun.h \ - functors/mem_fun.h \ - functors/functor_trait.h - functors/slot.cc: \ functors/slot.h \ functors/slot_base.h \ functors/functor_trait.h -%.h: macros/%.h.m4 $(m4_dir)/template.macros.m4 | $(build_subdirs) - $(AM_V_GEN)$(M4) -I $(m4_dir) -I macros $< >$@ - -%.cc: macros/%.cc.m4 $(m4_dir)/template.macros.m4 | $(build_subdirs) - $(AM_V_GEN)$(M4) -I $(m4_dir) -I macros $< >$@ diff --git a/sigc++/adaptors/adaptor_base.h b/sigc++/adaptors/adaptor_base.h new file mode 100644 index 00000000..4d8fa24d --- /dev/null +++ b/sigc++/adaptors/adaptor_base.h @@ -0,0 +1,40 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_DEDUCE_RESULT_TYPE_H +#define SIGC_ADAPTORS_DEDUCE_RESULT_TYPE_H + +namespace sigc +{ + +// TODO: Is this necessary now that we don't need deduce_result_type? +/** A hint to the compiler. + * Functors which have all methods based on templates + * should publicly inherit from this hint. + * + * Adaptors don't inherit from this type directly. They use + * use sigc::adapts as a base type instead. sigc::adaptors + * wraps arbitrary functor types as well as function pointers + * and class methods. + * + * @ingroup adaptors + */ +struct adaptor_base +{ +}; + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_DEDUCE_RESULT_TYPE_H */ diff --git a/sigc++/adaptors/adaptor_trait.h b/sigc++/adaptors/adaptor_trait.h new file mode 100644 index 00000000..fbf8f6a0 --- /dev/null +++ b/sigc++/adaptors/adaptor_trait.h @@ -0,0 +1,180 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_ADAPTOR_TRAIT_H +#define SIGC_ADAPTORS_ADAPTOR_TRAIT_H + +#include //To get SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD +#include +#include +#include +#include +#include +#include + +/* + * The idea here is simple. To prevent the need to + * specializing every adaptor for every type of functor + * and worse non-functors like function pointers, we + * will make an adaptor trait which can take ordinary + * functors and make them adaptor functors for which + * we will of course be able to avoid excess copies. + * (in theory) + * + * this all depends on partial specialization to allow + * us to do + * functor_.template operator() (args); + * + * + * I don't understand much of the above. However, I can + * see that adaptors are implemented like they are because + * there is no way to extract the return type and the argument + * types from a functor type. Therefore, operator() is templated. + * It's instantiated in slot_call#<>::operator() where the + * argument types are known. The return type is finally determined + * via the callof<> template - a tricky way to detect the return + * type of a functor when the argument types are known. Martin. + */ + +namespace sigc +{ + +/** @defgroup adaptors Adaptors + * Adaptors are functors that alter the signature of a functor's + * operator()(). + * + * The adaptor types libsigc++ provides + * are created with bind(), bind_return(), hide(), hide_return(), + * retype_return(), retype(), compose(), exception_catch(), track_obj() + * and group(). + * + * You can easily derive your own adaptor type from sigc::adapts. + */ + +/** Converts an arbitrary functor into an adaptor type. + * All adaptor types in libsigc++ have + * a template operator() member of every argument count + * they support. These functions in turn invoke a stored adaptor's + * template operator(), processing the arguments and return + * value in a characteristic manner. Explicit function template + * instantiation is used to pass type hints thus saving copy costs. + * + * adaptor_functor is a glue between adaptors and arbitrary functors + * that just passes on the arguments. You won't use this type directly. + * + * The template argument @e T_functor determines the type of stored + * functor. + * + * @ingroup adaptors + */ +template +struct adaptor_functor : public adaptor_base +{ + /** Invokes the wrapped functor passing on the arguments. + * @return The return value of the functor invocation. + */ + decltype(auto) operator()() const { return functor_(); } + + /** Invokes the wrapped functor passing on the arguments. + * @param arg Arguments to be passed on to the functor. + * @return The return value of the functor invocation. + */ + template + decltype(auto) operator()(T_arg&&... arg) const + { + return std::invoke(functor_, std::forward(arg)...); + } + + /// Constructs an invalid functor. + adaptor_functor() = default; + + /** Constructs an adaptor_functor object that wraps the passed functor. + * @param functor Functor to invoke from operator()(). + */ + explicit adaptor_functor(const T_functor& functor) : functor_(functor) {} + + /** Constructs an adaptor_functor object that wraps the passed (member) + * function pointer. + * @param type Pointer to function or class method to invoke from operator()(). + */ + template + explicit adaptor_functor(const T_type& type) : functor_(type) + { + } + + /// Functor that is invoked from operator()(). + mutable T_functor functor_; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::adaptor_functor performs a functor + * on the functor stored in the sigc::adaptor_functor object. + * + * @ingroup adaptors + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, const adaptor_functor& target) + { + sigc::visit_each(action, target.functor_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Trait that specifies what is the adaptor version of a functor type. + * Template specializations exist for sigc::adaptor_base-derived functors, + * for function pointers and for class methods. + * + * The template argument @e T_functor is the functor type to convert. + * @e I_isadaptor indicates whether @e T_functor inherits from sigc::adaptor_base. + * + * @ingroup adaptors + */ +template::value> +struct adaptor_trait; + +/** Trait that specifies the adaptor version of a functor type. + * This template specialization is used for types that inherit from adaptor_base. + * adaptor_type is equal to @p T_functor in this case. + */ +template +struct adaptor_trait +{ + using adaptor_type = T_functor; +}; + +/** Trait that specifies the adaptor version of a functor type. + * This template specialization is used for arbitrary functors, + * for function pointers and for class methods. + * The latter are converted into @p pointer_functor or @p mem_functor types. + * adaptor_type is equal to @p adaptor_functor. + */ +template +struct adaptor_trait +{ +private: + using functor_type = typename functor_trait::functor_type; + +public: + using adaptor_type = adaptor_functor; +}; + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_ADAPTOR_TRAIT_H */ diff --git a/sigc++/adaptors/adaptors.h b/sigc++/adaptors/adaptors.h index 2353890e..81403913 100644 --- a/sigc++/adaptors/adaptors.h +++ b/sigc++/adaptors/adaptors.h @@ -1,6 +1,4 @@ -// -*- c++ -*- -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -13,12 +11,10 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_ADAPTOR_HPP_ -#define _SIGC_ADAPTOR_HPP_ +#ifndef SIGC_ADAPTOR_HPP +#define SIGC_ADAPTOR_HPP #include #include @@ -29,4 +25,4 @@ #include #include -#endif /* _SIGC_ADAPTOR_HPP_ */ +#endif /* SIGC_ADAPTOR_HPP */ diff --git a/sigc++/adaptors/adapts.h b/sigc++/adaptors/adapts.h new file mode 100644 index 00000000..50dd31c9 --- /dev/null +++ b/sigc++/adaptors/adapts.h @@ -0,0 +1,109 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_ADAPTS_H +#define SIGC_ADAPTORS_ADAPTS_H + +#include //To get SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD +#include +#include +#include +#include +#include + +namespace sigc +{ + +// Doxygen (at least version 1.8.4) removes blank lines in a code block. +// That's why there are empty comment lines in the following code block. +/** Base type for adaptors. + * sigc::adapts wraps adaptors, functors, function pointers and class methods. + * It contains a single member functor which is always a sigc::adaptor_base. + * The adaptor_type alias defines the exact type that is used + * to store the adaptor, functor, function pointer or class method passed + * into the constructor. It differs from @a T_functor unless @a T_functor + * inherits from sigc::adaptor_base. + * + * @par Example of a simple adaptor: + * @code + * namespace my_ns + * { + * template + * struct my_adaptor : public sigc::adapts + * { + * // + * decltype(auto) + * operator()() const; + * // + * template + * decltype(auto) + * operator()(T_arg1 arg1) const; + * // + * template + * decltype(auto) + * operator()(T_arg1 arg1, T_arg2 arg2) const; + * // + * // Constructs a my_adaptor object that wraps the passed functor. + * // Initializes adapts::functor_, which is invoked from operator()(). + * explicit my_adaptor(const T_functor& functor) + * : sigc::adapts(functor) {} + * }; + * } // end namespace my_ns + * // + * // Specialization of sigc::visitor for my_adaptor. + * namespace sigc + * { + * template + * struct visitor > + * { + * template + * static void do_visit_each(const T_action& action, + * const my_ns::my_adaptor& target) + * { + * sigc::visit_each(action, target.functor_); + * } + * }; + * } // end namespace sigc + * @endcode + * + * If you implement your own adaptor, you must also provide your specialization + * of sigc::visitor<>::do_visit_each<>() that will forward the call to the functor(s) + * your adapter is wrapping. Otherwise, pointers stored within the functor won't be + * invalidated when a sigc::trackable object is destroyed and you can end up + * executing callbacks on destroyed objects. + * + * Your specialization of sigc::visitor<> must be in namespace sigc. + * + * @ingroup adaptors + */ +template +struct adapts : public adaptor_base +{ +private: + using adaptor_type = typename adaptor_trait::adaptor_type; + +public: + /** Constructs an adaptor that wraps the passed functor. + * @param functor Functor to invoke from operator()(). + */ + explicit adapts(const T_functor& functor) : functor_(functor) {} + + /// Adaptor that is invoked from operator()(). + mutable adaptor_type functor_; +}; + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_ADAPTS_H */ diff --git a/sigc++/adaptors/bind.h b/sigc++/adaptors/bind.h new file mode 100644 index 00000000..66af8ff9 --- /dev/null +++ b/sigc++/adaptors/bind.h @@ -0,0 +1,288 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_BIND_H +#define SIGC_ADAPTORS_BIND_H + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sigc +{ + +/** @defgroup bind bind(), bind_return() + * sigc::bind() alters an arbitrary functor by fixing arguments to certain values. + * For single argument binding, overloads of sigc::bind() are provided that let you + * specify the zero-based position of the argument to fix with the first template parameter. + * (A value of @p -1 fixes the last argument so sigc::bind<-1>() gives the same result as + * sigc::bind().) + * The types of the arguments can optionally be specified if not deduced. + * + * @par Examples: + * @code + * void foo(int, int, int); + * // single argument binding ... + * sigc::bind(&foo,1)(2,3); //fixes the last (third) argument and calls foo(2,3,1) + * sigc::bind<-1>(&foo,1)(2,3); //same as bind(&foo,1)(2,3) (calls foo(2,3,1)) + * sigc::bind<0>(&foo,1)(2,3); //fixes the first argument and calls foo(1,2,3) + * sigc::bind<1>(&foo,1)(2,3); //fixes the second argument and calls foo(2,1,3) + * sigc::bind<2>(&foo,1)(2,3); //fixes the third argument and calls foo(2,3,1) + * // multi argument binding ... + * sigc::bind(&foo,1,2)(3); //fixes the last two arguments and calls foo(3,1,2) + * sigc::bind(&foo,1,2,3)(); //fixes all three arguments and calls foo(1,2,3) + * @endcode + * + * The functor that sigc::bind() returns can be passed directly into + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()". + * + * @par Example: + * @code + * sigc::signal some_signal; + * void foo(int); + * some_signal.connect(sigc::bind(&foo,1)); + * @endcode + * + * sigc::bind_return() alters an arbitrary functor by + * fixing its return value to a certain value. + * + * @par Example: + * @code + * void foo(); + * std::cout << sigc::bind_return(&foo, 5)(); // calls foo() and returns 5 + * @endcode + * + * You can bind references to functors by passing the objects through + * the std::ref() helper function. + * + * @par Example: + * @code + * int some_int; + * sigc::signal some_signal; + * void foo(int&); + * some_signal.connect(sigc::bind(&foo, std::ref(some_int))); + * @endcode + * + * If you bind an object of a sigc::trackable derived type to a functor + * by reference, a slot assigned to the bind adaptor is cleared automatically + * when the object goes out of scope. + * + * @par Example: + * @code + * struct bar : public sigc::trackable {} some_bar; + * sigc::signal some_signal; + * void foo(bar&); + * some_signal.connect(sigc::bind(&foo, std::ref(some_bar))); + * // disconnected automatically if some_bar goes out of scope + * @endcode + * + * @ingroup adaptors + */ + +namespace internal +{ + +template +struct TransformEachInvoker +{ + // We take T_element as non-const because invoke() is not const. + // TODO: Take element as T_element&& ? + constexpr static decltype(auto) transform(T_element& element) { return element.invoke(); } +}; + +} // namespace internal + +/** Adaptor that binds arguments to the wrapped functor. + * Use the convenience function sigc::bind() to create an instance of sigc::bind_functor. + * + * The following template arguments are used: + * - @e I_location Zero-based position of the argument to fix (@p -1 for the last argument). + * - @e T_bound Types of the bound argument. + * - @e T_functor Type of the functor to wrap. + * + * @ingroup bind + */ +template +struct bind_functor : public adapts +{ + /** Invokes the wrapped functor passing on the arguments. + * bound_ is passed as the next argument. + * @param arg Arguments to be passed on to the functor. + * @return The return value of the functor invocation. + */ + template + decltype(auto) operator()(T_arg&&... arg) + { + // For instance, if I_location is 1, and arg has 4 arguments, + // we would want to call operator() with (arg0, bound, arg1, arg2). + + using tuple_type_args = std::tuple...>; + const auto t_args = std::tuple(std::forward(arg)...); + constexpr auto t_args_size = std::tuple_size::value; + + // Prevent calling tuple_start<> with values that will cause a compilation error. + static_assert(I_location <= t_args_size, + "I_location must be less than or equal to the number of arguments."); + + const auto t_start = internal::tuple_start(t_args); + const auto t_bound = internal::tuple_transform_each(bound_); + const auto t_end = internal::tuple_end(t_args); + const auto t_with_bound = std::tuple_cat(t_start, t_bound, t_end); + + return std::apply(this->functor_, t_with_bound); + } + + /** Constructs a bind_functor object that binds an argument to the passed functor. + * @param func Functor to invoke from operator()(). + * @param bound Argument to bind to the functor. + */ + bind_functor(type_trait_take_t func, type_trait_take_t... bound) + : adapts(func), bound_(bound...) + { + } + + // public to avoid template friend declarations (used by visitor::do_visit_each()) + /// The arguments bound to the functor. + std::tuple...> bound_; +}; + +/** Adaptor that binds argument(s) to the wrapped functor. + * This template specialization fixes the last argument(s) of the wrapped functor. + * + * @ingroup bind + */ +template +struct bind_functor<-1, T_functor, T_type...> : public adapts +{ +public: + /** Invokes the wrapped functor passing on the arguments. + * bound_ is passed as the next argument. + * @param arg Arguments to be passed on to the functor. + * @return The return value of the functor invocation. + */ + template + decltype(auto) operator()(T_arg&&... arg) + { + // For instance, if arg has 4 arguments, + // we would want to call operator() with (arg0, arg1, arg2, bound). + + const auto t_args = std::tuple(std::forward(arg)...); + const auto t_bound = internal::tuple_transform_each(bound_); + const auto t_with_bound = std::tuple_cat(t_args, t_bound); + + return std::apply(this->functor_, t_with_bound); + } + + /** Constructs a bind_functor object that binds an argument to the passed functor. + * @param func Functor to invoke from operator()(). + * @param bound Arguments to bind to the functor. + */ + bind_functor(type_trait_take_t func, type_trait_take_t... bound) + : adapts(func), bound_(bound...) + { + } + + // public to avoid template friend declarations (used by visitor::do_visit_each()) + /// The argument bound to the functor. + std::tuple...> bound_; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::bind_functor performs a functor on the + * functor and on the object instances stored in the sigc::bind_functor object. + * + * @ingroup bind + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const bind_functor& target) + { + sigc::visit_each(action, target.functor_); + sigc::visit_each(action, std::get<0>(target.bound_)); + } +}; + +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::bind_functor performs a functor on the + * functor and on the object instances stored in the sigc::bind_functor object. + * + * @ingroup bind + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const bind_functor<-1, T_functor, T_type...>& target) + { + sigc::visit_each(action, target.functor_); + + sigc::internal::tuple_for_each(target.bound_, action); + } +}; + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Creates an adaptor of type sigc::bind_functor which binds the passed argument to the passed + * functor. + * The optional template argument @e I_location specifies the zero-based + * position of the argument to be fixed (@p -1 stands for the last argument). + * + * @param func Functor that should be wrapped. + * @param b Arguments to bind to @e func. + * @return Adaptor that executes @e func with the bound argument on invocation. + * + * @ingroup bind + */ +template +inline decltype(auto) +bind(const T_functor& func, T_bound... b) +{ + return bind_functor(func, b...); +} + +/** Creates an adaptor of type sigc::bind_functor which fixes the last arguments of the passed + * functor. + * This function overload fixes the last arguments of @e func. + * + * @param func Functor that should be wrapped. + * @param b Arguments to bind to @e func. + * @return Adaptor that executes func with the bound argument on invocation. + * + * @ingroup bind + */ +template +inline decltype(auto) +bind(const T_functor& func, T_type... b) +{ + return bind_functor<-1, T_functor, T_type...>(func, b...); +} + +} /* namespace sigc */ + +#endif /* SIGC_ADAPTORS_BIND_H */ diff --git a/sigc++/adaptors/bind_return.h b/sigc++/adaptors/bind_return.h new file mode 100644 index 00000000..5c8a3348 --- /dev/null +++ b/sigc++/adaptors/bind_return.h @@ -0,0 +1,113 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_BIND_RETURN_H +#define SIGC_ADAPTORS_BIND_RETURN_H +#include +#include + +namespace sigc +{ + +/** Adaptor that fixes the return value of the wrapped functor. + * Use the convenience function sigc::bind_return() to create an instance of + * sigc::bind_return_functor. + * + * The following template arguments are used: + * - @e T_return Type of the fixed return value. + * - @e T_functor Type of the functor to wrap. + * + * @ingroup bind + */ +template +struct bind_return_functor : public adapts +{ + /** Invokes the wrapped functor dropping its return value. + * @return The fixed return value. + */ + typename unwrap_reference::type operator()(); + + /** Invokes the wrapped functor passing on the arguments. + * @param a Arguments to be passed on to the functor. + * @return The fixed return value. + */ + template + inline typename unwrap_reference::type operator()(T_arg... a) + { + std::invoke(this->functor_, a...); + return ret_value_.invoke(); + } + + /** Constructs a bind_return_functor object that fixes the return value to @p ret_value. + * @param functor Functor to invoke from operator()(). + * @param ret_value Value to return from operator()(). + */ + bind_return_functor(type_trait_take_t functor, type_trait_take_t ret_value) + : adapts(functor), ret_value_(ret_value) + { + } + + /// The fixed return value. + bound_argument ret_value_; // public, so that visit_each() can access it +}; + +template +typename unwrap_reference::type +bind_return_functor::operator()() +{ + std::invoke(this->functor_); + return ret_value_.invoke(); +} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::bind_return_functor performs a functor on the + * functor and on the object instance stored in the sigc::bind_return_functor object. + * + * @ingroup bind + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const bind_return_functor& target) + { + sigc::visit_each(action, target.ret_value_); + sigc::visit_each(action, target.functor_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Creates an adaptor of type sigc::bind_return_functor which fixes the return value of the passed + * functor to the passed argument. + * + * @param functor Functor that should be wrapped. + * @param ret_value Argument to fix the return value of @e functor to. + * @return Adaptor that executes @e functor on invocation and returns @e ret_value. + * + * @ingroup bind + */ +template +inline bind_return_functor +bind_return(const T_functor& functor, T_return ret_value) +{ + return bind_return_functor(functor, ret_value); +} + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_BIND_RETURN_H */ diff --git a/sigc++/adaptors/bound_argument.h b/sigc++/adaptors/bound_argument.h index 05796827..a389b91e 100644 --- a/sigc++/adaptors/bound_argument.h +++ b/sigc++/adaptors/bound_argument.h @@ -1,5 +1,4 @@ -/* - * Copyright 2005, The libsigc++ Development Team +/* Copyright 2005 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,29 +11,28 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library; if not, see . */ -#ifndef _SIGC_BOUND_ARGUMENT_H_ -#define _SIGC_BOUND_ARGUMENT_H_ - +#ifndef SIGC_BOUND_ARGUMENT_H +#define SIGC_BOUND_ARGUMENT_H #include #include +namespace sigc +{ -namespace sigc { - -/** A bound_argument object stores a bound (for instance, with sigc::bind(), or sigc::bind_return()) argument. +/** A bound_argument object stores a bound (for instance, with sigc::bind(), or + * sigc::bind_return()) argument. * - * If Foo is a wrapped reference to a class Bar (reference_wrapper) then this + * If Foo is a wrapped reference to a class Bar (std::reference_wrapper) then this * object is implemented on top of a limit_reference. When the slot is * invoked, the limit_reference::invoke() method provides the argument (a Bar&). * When the slot is visited (e.g. visit_each<>()), we simply visit the limit_reference, * which will visit the derived type, or a sigc::trackable base if necessary. * - * Likewise, If Foo is a wrapped const reference to a class Bar (const_reference_wrapper) + * Likewise, If Foo is a wrapped const reference to a class Bar (std::reference_wrapper) * then this object is implemented on top of a const_limit_reference. * * If Foo is something else (such as an argument that is bound by value) bound_argument just @@ -46,28 +44,24 @@ namespace sigc { * The general template implementation is used for parameters that are passed by value. * @e T_type The type of the bound argument. */ -template +template class bound_argument { public: /** Constructor. - * @param _A_argument The argument to bind. + * @param arg The argument to bind. */ - bound_argument(const T_type& _A_argument) - : visited_(_A_argument) - {} + bound_argument(const T_type& arg) : visited_(arg) {} /** Retrieve the entity to visit in visit_each(). * @return The bound argument. */ - inline const T_type& visit() const - { return visited_; } + inline const T_type& visit() const { return visited_; } /** Retrieve the entity to pass to the bound functor or return. * @return The bound argument. */ - inline T_type& invoke() - { return visited_; } + inline T_type& invoke() { return visited_; } private: /** The value of the argument. @@ -75,33 +69,29 @@ class bound_argument T_type visited_; }; -//Template specialization: +// Template specialization: /** bound_argument object for a bound argument that is passed by bind() or - * returned by bind_return() by reference, specialized for reference_wrapper<> types. + * returned by bind_return() by reference, specialized for std::reference_wrapper<> types. * @e T_wrapped The type of the bound argument. */ -template -class bound_argument< reference_wrapper > +template +class bound_argument> { public: /** Constructor. - * @param _A_argument The argument to bind. + * @param arg The argument to bind. */ - bound_argument(const reference_wrapper& _A_argument) - : visited_(unwrap(_A_argument)) - {} + bound_argument(const std::reference_wrapper& arg) : visited_(unwrap(arg)) {} /** Retrieve the entity to visit in visit_each(). * @return The limited_reference to the bound argument. */ - inline const limit_reference& visit() const - { return visited_; } + inline const limit_reference& visit() const { return visited_; } /** Retrieve the entity to pass to the bound functor or return. * @return The bound argument. */ - inline T_wrapped& invoke() - { return visited_.invoke(); } + inline T_wrapped& invoke() { return visited_.invoke(); } private: /** The limited_reference to the bound argument. @@ -113,33 +103,29 @@ class bound_argument< reference_wrapper > * returned by bind_return() by const reference, specialized for const reference_wrapper<> types. * - @e T_wrapped The type of the bound argument. */ -template -class bound_argument< const_reference_wrapper > +template +class bound_argument> { public: /** Constructor. - * @param _A_argument The argument to bind. + * @param arg The argument to bind. */ - bound_argument(const const_reference_wrapper& _A_argument) - : visited_(unwrap(_A_argument)) - {} + bound_argument(const std::reference_wrapper& arg) : visited_(unwrap(arg)) {} /** Retrieve the entity to visit in visit_each(). * @return The const_limited_reference to the bound argument. */ - inline const const_limit_reference& visit() const - { return visited_; } + inline const limit_reference& visit() const { return visited_; } /** Retrieve the entity to pass to the bound functor or return. * @return The bound argument. */ - inline const T_wrapped& invoke() - { return visited_.invoke(); } + inline const T_wrapped& invoke() { return visited_.invoke(); } private: /** The const_limited_reference to the bound argument. */ - const_limit_reference visited_; + limit_reference visited_; }; #ifndef DOXYGEN_SHOULD_SKIP_THIS @@ -148,22 +134,20 @@ class bound_argument< const_reference_wrapper > * method. * @tparam T_type The type of bound_argument. * @tparam T_action The type of functor to invoke. - * @param _A_action The functor to invoke. - * @param _A_argument The visited instance. + * @param action The functor to invoke. + * @param arg The visited instance. */ -template -struct visitor > +template +struct visitor> { - template - static void do_visit_each(const T_action& _A_action, - const bound_argument& _A_argument) + template + static void do_visit_each(const T_action& action, const bound_argument& arg) { - sigc::visit_each(_A_action, _A_argument.visit()); + sigc::visit_each(action, arg.visit()); } }; #endif // DOXYGEN_SHOULD_SKIP_THIS } /* namespace sigc */ - -#endif /* _SIGC_BOUND_ARGUMENT_H_ */ +#endif /* SIGC_BOUND_ARGUMENT_H */ diff --git a/sigc++/adaptors/compose.h b/sigc++/adaptors/compose.h new file mode 100644 index 00000000..b472d6a7 --- /dev/null +++ b/sigc++/adaptors/compose.h @@ -0,0 +1,193 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_COMPOSE_H +#define SIGC_ADAPTORS_COMPOSE_H +#include +#include + +namespace sigc +{ + +/** @defgroup compose compose() + * sigc::compose() combines two or three arbitrary functors. + * On invocation, parameters are passed on to one or two getter functor(s). + * The return value(s) are then passed on to the setter function. + * + * @par Examples: + * @code + * float square_root(float a) { return sqrtf(a); } + * float sum(float a, float b) { return a+b; } + * std::cout << sigc::compose(&square_root, &sum)(9, 16); // calls square_root(sum(3,6)) + * std::cout << sigc::compose(&sum, &square_root, &square_root)(9); // calls sum(square_root(9), + * square_root(9)) + * @endcode + * + * The functor that sigc::compose() returns can be passed directly into + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()". + * + * @par Example: + * @code + * sigc::signal(float(float, float)> some_signal; + * some_signal.connect(sigc::compose(&square_root, &sum)); + * @endcode + * + * @ingroup adaptors + */ + +/** Adaptor that combines two functors. + * Use the convenience function sigc::compose() to create an instance of sigc::compose1_functor. + * + * The following template arguments are used: + * - @e T_setter Type of the setter functor to wrap. + * - @e T_getter Type of the getter functor to wrap. + * + * @ingroup compose + */ +template +struct compose1_functor : public adapts +{ + template + decltype(auto) operator()(T_arg&&... a) + { + return std::invoke(this->functor_, get_(std::forward(a)...)); + } + + /** Constructs a compose1_functor object that combines the passed functors. + * @param setter Functor that receives the return values of the invocation of @e getter1 and + * @e getter2. + * @param getter Functor to invoke from operator()(). + */ + compose1_functor(const T_setter& setter, const T_getter& getter) + : adapts(setter), get_(getter) + { + } + + T_getter get_; // public, so that visit_each() can access it +}; + +/** Adaptor that combines three functors. + * Use the convenience function sigc::compose() to create an instance of sigc::compose2_functor. + * + * The following template arguments are used: + * - @e T_setter Type of the setter functor to wrap. + * - @e T_getter1 Type of the first getter functor to wrap. + * - @e T_getter2 Type of the second getter functor to wrap. + * + * @ingroup compose + */ +template +struct compose2_functor : public adapts +{ + template + decltype(auto) operator()(T_arg... a) + { + return std::invoke(this->functor_, get1_(a...), get2_(a...)); + } + + /** Constructs a compose2_functor object that combines the passed functors. + * @param setter Functor that receives the return values of the invocation of @e getter1 and + * @e getter2. + * @param getter1 Functor to invoke from operator()(). + * @param getter2 Functor to invoke from operator()(). + */ + compose2_functor(const T_setter& setter, const T_getter1& getter1, const T_getter2& getter2) + : adapts(setter), get1_(getter1), get2_(getter2) + { + } + + T_getter1 get1_; // public, so that visit_each() can access it + T_getter2 get2_; // public, so that visit_each() can access it +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::compose1_functor performs a functor on the + * functors stored in the sigc::compose1_functor object. + * + * @ingroup compose + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const compose1_functor& target) + { + sigc::visit_each(action, target.functor_); + sigc::visit_each(action, target.get_); + } +}; + +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::compose2_functor performs a functor on the + * functors stored in the sigc::compose2_functor object. + * + * @ingroup compose + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const compose2_functor& target) + { + sigc::visit_each(action, target.functor_); + sigc::visit_each(action, target.get1_); + sigc::visit_each(action, target.get2_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Creates an adaptor of type sigc::compose1_functor which combines two functors. + * + * @param setter Functor that receives the return value of the invocation of @e getter. + * @param getter Functor to invoke from operator()(). + * @return Adaptor that executes @e setter with the value returned from invocation of @e + * getter. + * + * @ingroup compose + */ +template +inline compose1_functor +compose(const T_setter& setter, const T_getter& getter) +{ + return compose1_functor(setter, getter); +} + +/** Creates an adaptor of type sigc::compose2_functor which combines three functors. + * + * @param setter Functor that receives the return values of the invocation of @e getter1 and + * @e getter2. + * @param getter1 Functor to invoke from operator()(). + * @param getter2 Functor to invoke from operator()(). + * @return Adaptor that executes @e setter with the values return from invocation of @e + * getter1 and @e getter2. + * + * @ingroup compose + */ +template +inline compose2_functor +compose(const T_setter& setter, const T_getter1& getter1, const T_getter2& getter2) +{ + return compose2_functor(setter, getter1, getter2); +} + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_COMPOSE_H */ diff --git a/sigc++/adaptors/exception_catch.h b/sigc++/adaptors/exception_catch.h new file mode 100644 index 00000000..b2528b6a --- /dev/null +++ b/sigc++/adaptors/exception_catch.h @@ -0,0 +1,134 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_EXCEPTION_CATCH_H +#define SIGC_ADAPTORS_EXCEPTION_CATCH_H +#include + +namespace sigc +{ + +/* + functor adaptor: exception_catch(functor, catcher) + + usage: + + + Future directions: + The catcher should be told what type of return it needs to + return for multiple type functors, to do this the user + will need to derive from catcher_base. +*/ +/** @defgroup exception_catch exception_catch() + * sigc::exception_catch() catches an exception thrown from within + * the wrapped functor and directs it to a catcher functor. + * This catcher can then rethrow the exception and catch it with the proper type. + * + * Note that the catcher is expected to return the same type + * as the wrapped functor so that normal flow can continue. + * + * Catchers can be cascaded to catch multiple types, because uncaught + * rethrown exceptions proceed to the next catcher adaptor. + * + * @par Examples: + * @code + * struct my_catch + * { + * int operator()() + * { + * try { throw; } + * catch (std::range_error e) // catch what types we know + * { std::cerr << "caught " << e.what() << std::endl; } + * return 1; + * } + * } + * int foo(); // throws std::range_error + * sigc::exception_catch(&foo, my_catch())(); + * @endcode + * + * The functor that sigc::exception_catch() returns can be passed directly into + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()". + * + * @par Example: + * @code + * sigc::signal some_signal; + * some_signal.connect(sigc::exception_catch(&foo, my_catch)); + * @endcode + * + * @ingroup adaptors + */ + +template +struct exception_catch_functor : public adapts +{ + decltype(auto) operator()() + { + try + { + return std::invoke(this->functor_); + } + catch (...) + { + return catcher_(); + } + } + + template + decltype(auto) operator()(T_arg... a) + { + try + { + return std::invoke(this->functor_, a...); + } + catch (...) + { + return catcher_(); + } + } + + exception_catch_functor(const T_functor& func, const T_catcher& catcher) + : adapts(func), catcher_(catcher) + { + } + + T_catcher catcher_; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const exception_catch_functor& target) + { + sigc::visit_each(action, target.functor_); + sigc::visit_each(action, target.catcher_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +template +inline decltype(auto) +exception_catch(const T_functor& func, const T_catcher& catcher) +{ + return exception_catch_functor(func, catcher); +} + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_EXCEPTION_CATCH_H */ diff --git a/sigc++/adaptors/hide.h b/sigc++/adaptors/hide.h new file mode 100644 index 00000000..2dbdb4ae --- /dev/null +++ b/sigc++/adaptors/hide.h @@ -0,0 +1,167 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_HIDE_H +#define SIGC_ADAPTORS_HIDE_H + +#include +#include +#include + +namespace sigc +{ + +/** @defgroup hide hide(), hide_return() + * sigc::hide() alters an arbitrary functor in that it adds a parameter + * whose value is ignored on invocation of the returned functor. + * Thus you can discard one argument of a signal. + * + * You may optionally specify the zero-based position of the parameter + * to ignore as a template argument. The default is to ignore the last + * parameter. + * (A value of @p -1 adds a parameter at the end so sigc::hide<-1>() gives the same result as + sigc::hide().) + * + * The type of the parameter can optionally be specified if not deduced. + * + * @par Examples: + * @code + * void foo(int, int); + * // single argument hiding ... + * sigc::hide(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2) + * sigc::hide<-1>(&foo)(1,2,3); // same as sigc::hide(&foo)(1,2,3) (calls foo(1,2)) + * sigc::hide<0>(&foo)(1,2,3); // adds a dummy parameter at the beginning and calls foo(2,3) + * sigc::hide<1>(&foo)(1,2,3); // adds a dummy parameter in the middle and calls foo(1,3) + * sigc::hide<2>(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2) + * @endcode + * + * The functor that sigc::hide() returns can be passed directly into + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()". + * + * @par Example: + * @code + * sigc::signal some_signal; + * void foo(); + * some_signal.connect(sigc::hide(&foo)); + * @endcode + * + * sigc::hide() can be nested in order to discard multiple arguments. + * @par Example: + * @code + * // multiple argument hiding ... + * // adds two dummy parameters at the back and calls foo(1,2) + * sigc::hide(sigc::hide(&foo))(1,2,3,4); + * @endcode + + * sigc::hide_return() alters an arbitrary functor by + * dropping its return value, thus converting it to a void functor. + * + * @ingroup adaptors + */ + +/** Adaptor that adds a dummy parameter to the wrapped functor. + * Use the convenience function sigc::hide() to create an instance of sigc::hide_functor. + * + * The following template arguments are used: + * - @e I_location Zero-based position of the dummy parameter (@p -1 for the last parameter). + * - @e T_functor Type of the functor to wrap. + * + * @ingroup hide + */ +template +struct hide_functor : public adapts +{ + /** Invokes the wrapped functor, ignoring the argument at index @e I_location (0-indexed). + * @param a Arguments to be passed on to the functor, apart from the ignored argument. + * @return The return value of the functor invocation. + */ + template + decltype(auto) operator()(T_arg&&... a) + { + constexpr auto size = sizeof...(T_arg); + constexpr auto index_ignore = (I_location == -1 ? size - 1 : I_location); + const auto t = std::tuple(std::forward(a)...); + + const auto t_start = internal::tuple_start(t); + const auto t_end = internal::tuple_end(t); + const auto t_used = std::tuple_cat(t_start, t_end); + + return std::apply(this->functor_, t_used); + } + + /** Constructs a hide_functor object that adds a dummy parameter to the passed functor. + * @param func Functor to invoke from operator()(). + */ + explicit hide_functor(const T_functor& func) : adapts(func) {} +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::hide_functor performs a functor on the + * functor stored in the sigc::hide_functor object. + * + * @ingroup hide + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const hide_functor& target) + { + sigc::visit_each(action, target.functor_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Creates an adaptor of type sigc::hide_functor which adds a dummy parameter to the passed + * functor. + * The optional template argument @e I_location specifies the zero-based + * position of the dummy parameter in the returned functor (@p -1 stands for the last parameter). + * + * @param func Functor that should be wrapped. + * @return Adaptor that executes @e func, ignoring the value of the dummy parameter. + * + * @ingroup hide + */ +template +inline decltype(auto) +hide(const T_functor& func) +{ + return hide_functor(func); +} + +/** Creates an adaptor of type sigc::hide_functor which adds a dummy parameter to the passed + * functor. + * This overload adds a dummy parameter at the back of the functor's parameter list. + * + * @param func Functor that should be wrapped. + * @return Adaptor that executes @e func, ignoring the value of the last parameter. + * + * @ingroup hide + */ +template +inline decltype(auto) +hide(const T_functor& func) +{ + return hide_functor<-1, T_functor>(func); +} + +} /* namespace sigc */ + +#endif /* SIGC_ADAPTORS_HIDE_H */ diff --git a/sigc++/adaptors/lambda/macros/base.h.m4 b/sigc++/adaptors/lambda/macros/base.h.m4 deleted file mode 100644 index 083bf851..00000000 --- a/sigc++/adaptors/lambda/macros/base.h.m4 +++ /dev/null @@ -1,210 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) -include(template.macros.m4) - -define([LAMBDA_DO],[dnl - template - typename deduce_result_type::type - operator ()(LOOP(T_arg%1 _A_%1, $1)) const - { return value_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_%1, $1)); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_%1, $1)) const - { return value_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_%1, $1)); - } - #endif //SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - -])dnl -define([LAMBDA_DO_VALUE],[dnl - template - result_type operator ()(LOOP(T_arg%1, $1)) const - { return value_; } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - result_type sun_forte_workaround(LOOP(T_arg%1, $1)) const - { return value_; } - #endif //SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - -])dnl - -divert(0)dnl -#ifndef _SIGC_LAMBDA_BASE_HPP_ -#define _SIGC_LAMBDA_BASE_HPP_ -#include -#include -#include - -_DEPRECATE_IFDEF_START - -namespace sigc { - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -// libsigc++'s lambda functions have been removed from the API. -// Some code must be kept until we can break ABI. -/** @defgroup lambdas Lambdas - * libsigc++ ships with basic lambda functionality and the sigc::group adaptor, - * which uses lambdas to transform a functor's parameter list. - * - * The lambda selectors sigc::_1, sigc::_2, ..., sigc::_7 are used to select the - * first, second, ..., seventh argument from a list. - * - * @par Examples: - * @code - * std::cout << sigc::_1(10,20,30); // returns 10 - * std::cout << sigc::_2(10,20,30); // returns 20 - * @endcode - * - * Operators are defined so that, for example, lambda selectors can be used as - * placeholders in arithmetic expressions. - * - * @par Examples: - * @code - * std::cout << (sigc::_1 + 5)(3); // returns (3 + 5) - * std::cout << (sigc::_1 * sigc::_2)(7,10); // returns (7 * 10) - * @endcode - * - * If your compiler supports C++11 lambda expressions, they are often a good - * alternative to libsigc++'s lambda expressions. The following examples are - * equivalent to the previous ones. - * @code - * [[]] (int x, int, int) -> int { return x; }(10,20,30); // returns 10 - * [[]] (int, int y, int) -> int { return y; }(10,20,30); // returns 20 - * [[]] (int x) -> int { return x + 5; }(3); // returns (3 + 5) - * [[]] (int x, int y) -> int { return x * y; }(7,10); // returns (7 * 10) - * @endcode - * - * @deprecated Use C++11 lambda expressions or %std::bind() instead. - */ - -/** A hint to the compiler. - * All lambda types publically inherit from this hint. - * - * @deprecated Use C++11 lambda expressions instead. - * - * @ingroup lambdas - */ -struct lambda_base : public adaptor_base {}; - -// Forward declaration of lambda. -template struct lambda; - -namespace internal { - -/** Abstracts lambda functionality. - * Objects of this type store a value that may be of type lambda itself. - * In this case, operator()() executes the lambda (a lambda is always a functor at the same time). - * Otherwise, operator()() simply returns the stored value. - * - * @deprecated Use C++11 lambda expressions instead. - * - * @ingroup lambdas - */ -template ::value> struct lambda_core; - -/** Abstracts lambda functionality (template specialization for lambda values). - * - * @deprecated Use C++11 lambda expressions instead. - * - * @ingroup lambdas - */ -template -struct lambda_core : public lambda_base -{ - template - struct deduce_result_type - { typedef typename T_type::template deduce_result_type::type type; }; - typedef typename T_type::result_type result_type; - typedef T_type lambda_type; - - result_type - operator()() const; - -FOR(1,CALL_SIZE,[[LAMBDA_DO(%1)]])dnl - lambda_core() {} - - explicit lambda_core(const T_type& v) - : value_(v) {} - - T_type value_; -}; - - -} /* namespace internal */ - - -// forward declarations for lambda operators other and other -template -struct other; -struct subscript; -struct assign; - -template -struct lambda_operator; - -template -struct unwrap_lambda_type; - -/** Lambda type. - * Objects of this type store a value that may be of type lambda itself. - * In this case, operator()() executes the lambda (a lambda is always a functor at the same time). - * Otherwise, operator()() simply returns the stored value. - * The assign and subscript operators are defined to return a lambda operator. - * - * @deprecated Use C++11 lambda expressions instead. - * - * @ingroup lambdas - */ -template -struct lambda : public internal::lambda_core -{ - typedef lambda self; - - lambda() - {} - - lambda(typename type_trait::take v) - : internal::lambda_core(v) - {} - - // operators for other - template - lambda, self, typename unwrap_lambda_type::type> > - operator [[]] (const T_arg& a) const - { typedef lambda_operator, self, typename unwrap_lambda_type::type> lambda_operator_type; - return lambda(lambda_operator_type(this->value_, unwrap_lambda_value(a))); } - - // operators for other - template - lambda, self, typename unwrap_lambda_type::type> > - operator = (const T_arg& a) const - { typedef lambda_operator, self, typename unwrap_lambda_type::type> lambda_operator_type; - return lambda(lambda_operator_type(this->value_, unwrap_lambda_value(a))); } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -} /* namespace sigc */ - -_DEPRECATE_IFDEF_END - -#endif /* _SIGC_LAMBDA_BASE_HPP_ */ diff --git a/sigc++/adaptors/lambda/macros/lambda.cc.m4 b/sigc++/adaptors/lambda/macros/lambda.cc.m4 deleted file mode 100644 index f9fa909f..00000000 --- a/sigc++/adaptors/lambda/macros/lambda.cc.m4 +++ /dev/null @@ -1,36 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) -include(template.macros.m4) -divert(0)dnl -#include - -_DEPRECATE_IFDEF_START - -namespace sigc { - -// sigc::_1 .. sigc::_7 must be kept until we can break ABI. -// See https://bugzilla.gnome.org/show_bug.cgi?id=755550 -// The extern declarations have been moved from select.h, to keep them out of the API. -// Without them the const sigc::_1 .. sigc::_7 would be local to this .cc file. -FOR(1,CALL_SIZE,[[extern SIGC_API const lambda _%1; -]]) -FOR(1,CALL_SIZE,[[const lambda _%1; -]]) -} /* namespace sigc */ - -_DEPRECATE_IFDEF_END diff --git a/sigc++/adaptors/lambda/macros/select.h.m4 b/sigc++/adaptors/lambda/macros/select.h.m4 deleted file mode 100644 index ab512a66..00000000 --- a/sigc++/adaptors/lambda/macros/select.h.m4 +++ /dev/null @@ -1,77 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) -include(template.macros.m4) - -dnl -dnl Macros to make select arguments -define([LAMBDA_SELECT_DO],[dnl - template -dnl T_arg$1 operator ()(LOOP(T_arg%1 _A_%1, $2)) const { return _A_$1; } - T_arg$1 operator ()(LIST(FOR(1,eval($1-1),[T_arg%1,]),T_arg$1 _A_$1,FOR(eval($1+1),$2,[T_arg%1,]))) const { return _A_$1; } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - //Does not work: T_arg$1 sun_forte_workaround(LOOP(T_arg%1 _A_%1, $2)) const { return operator()( LOOP(_A_%1, $2) ); } - T_arg$1 sun_forte_workaround(LIST(FOR(1,eval($1-1),[T_arg%1,]),T_arg$1 _A_$1,FOR(eval($1+1),$2,[T_arg%1,]))) const { return _A_$1; } - #endif - -]) -define([LAMBDA_SELECT],[dnl -struct lambda_select$1 : public lambda_base -{ - template - struct deduce_result_type - { typedef T_arg$1 type; }; - typedef void result_type; // no operator ()() overload - - void operator ()() const; // not implemented -FOR($1, $2,[[LAMBDA_SELECT_DO($1,%1)]])dnl -}; - -]) -define([LAMBDA_SELECTOR],[dnl -/** Lambda selector. - * - * @deprecated Use C++11 lambda expressions or %std::bind() instead of libsigc++ lambdas and sigc::group(). - * - * @ingroup lambdas - */ -extern SIGC_API const lambda _$1; - -]) - -divert(0)dnl -#ifndef _SIGC_LAMBDA_SELECT_HPP_ -#define _SIGC_LAMBDA_SELECT_HPP_ -#include - -_DEPRECATE_IFDEF_START - -namespace sigc { - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -namespace internal { -FOR(1,CALL_SIZE,[[LAMBDA_SELECT(%1,CALL_SIZE)]])dnl -} /* namespace internal */ - -#endif // DOXYGEN_SHOULD_SKIP_THIS -} /* namespace sigc */ - -_DEPRECATE_IFDEF_END - -#endif /* _SIGC_LAMBDA_SELECT_HPP_ */ diff --git a/sigc++/adaptors/macros/adaptor_trait.h.m4 b/sigc++/adaptors/macros/adaptor_trait.h.m4 deleted file mode 100644 index a7a06137..00000000 --- a/sigc++/adaptors/macros/adaptor_trait.h.m4 +++ /dev/null @@ -1,326 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) -include(template.macros.m4) - -dnl -dnl The idea here is simple. To prevent the need to -dnl specializing every adaptor for every type of functor -dnl and worse non-functors like function pointers, we -dnl will make an adaptor trait which can take ordinary -dnl functors and make them adaptor functors for which -dnl we will of course be able to avoid excess copies. -dnl (in theory) -dnl -dnl this all depends on partial specialization to allow -dnl us to do -dnl functor_.template operator() (args); -dnl - -dnl I don't understand much of the above. However, I can -dnl see that adaptors are implemented like they are because -dnl there is no way to extract the return type and the argument -dnl types from a functor type. Therefore, operator() is templated. -dnl It's instatiated in slot_call#<>::operator() where the -dnl argument types are known. The return type is finally determined -dnl via the callof<> template - a tricky way to detect the return -dnl type of a functor when the argument types are known. Martin. - -]) -define([ADAPTOR_DO],[dnl -ifelse($1,0,[dnl -dnl typename internal::callof_safe0::result_type // doesn't compile if T_functor has an overloaded operator()! -dnl typename functor_trait::result_type -dnl operator()() const -dnl { return functor_(); } -],[dnl - /** Invokes the wrapped functor passing on the arguments.dnl -FOR(1, $1,[ - * @param _A_arg%1 Argument to be passed on to the functor.]) - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_arg%1, $1)) const - { return functor_(LOOP(_A_arg%1, $1)); } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_arg%1, $1)) const - { //Just calling operator() tries to copy the argument: - return functor_(LOOP(_A_arg%1, $1)); - } - #endif - -])dnl -]) - -divert(0)dnl -_FIREWALL([ADAPTORS_ADAPTOR_TRAIT]) -#include //To get SIGC_TEMPLATE_KEYWORD_OPERATOR_OVERLOAD -#include -#include -#include -#include -#include - -namespace sigc { - -// Call either operator()<>() or sun_forte_workaround<>(), -// depending on the compiler: -#ifdef SIGC_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - #define SIGC_WORKAROUND_OPERATOR_PARENTHESES template operator() - #define SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD -#else - #ifdef SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - #define SIGC_WORKAROUND_OPERATOR_PARENTHESES operator() - #define SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - #else - #define SIGC_WORKAROUND_OPERATOR_PARENTHESES sun_forte_workaround - #endif -#endif - - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -template struct adapts; -#endif - -/** @defgroup adaptors Adaptors - * Adaptors are functors that alter the signature of a functor's - * operator()(). - * - * The adaptor types libsigc++ provides - * are created with bind(), bind_return(), hide(), hide_return(), - * retype_return(), retype(), compose(), exception_catch(), track_obj() - * and group(). - * - * You can easily derive your own adaptor type from sigc::adapts. - */ - -/** Converts an arbitrary functor into an adaptor type. - * All adaptor types in libsigc++ have - * a template operator() member of every argument count - * they support. These functions in turn invoke a stored adaptor's - * template operator(), processing the arguments and return - * value in a characteristic manner. Explicit function template - * instantiation is used to pass type hints thus saving copy costs. - * - * adaptor_functor is a glue between adaptors and arbitrary functors - * that just passes on the arguments. You won't use this type directly. - * - * The template argument @e T_functor determines the type of stored - * functor. - * - * @ingroup adaptors - */ -template -struct adaptor_functor : public adaptor_base -{ -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef sigc::deduce_result_t type; }; -#endif - typedef typename functor_trait::result_type result_type; - - /** Invokes the wrapped functor passing on the arguments. - * @return The return value of the functor invocation. - */ - result_type - operator()() const; - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - result_type sun_forte_workaround() const - { return operator(); } - #endif - -FOR(0,CALL_SIZE,[[ADAPTOR_DO(%1)]])dnl - /// Constructs an invalid functor. - adaptor_functor() - {} - - /** Constructs an adaptor_functor object that wraps the passed functor. - * @param _A_functor Functor to invoke from operator()(). - */ - explicit adaptor_functor(const T_functor& _A_functor) - : functor_(_A_functor) - {} - - /** Constructs an adaptor_functor object that wraps the passed (member) - * function pointer. - * @param _A_type Pointer to function or class method to invoke from operator()(). - */ - template - explicit adaptor_functor(const T_type& _A_type) - : functor_(_A_type) - {} - - /// Functor that is invoked from operator()(). - mutable T_functor functor_; -}; - -template -typename adaptor_functor::result_type -adaptor_functor::operator()() const - { return functor_(); } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::adaptor_functor performs a functor - * on the functor stored in the sigc::adaptor_functor object. - * - * @ingroup adaptors - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const adaptor_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Trait that specifies what is the adaptor version of a functor type. - * Template specializations for sigc::adaptor_base derived functors, - * for function pointers and for class methods are provided. - * - * The template argument @e T_functor is the functor type to convert. - * @e I_isadaptor indicates whether @e T_functor inherits from sigc::adaptor_base. - * - * @ingroup adaptors - */ -#ifndef DOXYGEN_SHOULD_SKIP_THIS -template ::value> struct adaptor_trait; -#else -template ::value> struct adaptor_trait {}; -#endif - -/** Trait that specifies what is the adaptor version of a functor type. - * This template specialization is used for types that inherit from adaptor_base. - * adaptor_type is equal to @p T_functor in this case. - */ -template -struct adaptor_trait -{ - typedef typename T_functor::result_type result_type; - typedef T_functor functor_type; - typedef T_functor adaptor_type; -}; - -/** Trait that specifies what is the adaptor version of a functor type. - * This template specialization is used for arbitrary functors, - * for function pointers and for class methods are provided. - * The latter are converted into @p pointer_functor or @p mem_functor types. - * adaptor_type is equal to @p adaptor_functor. - */ -template -struct adaptor_trait -{ - typedef typename functor_trait::result_type result_type; - typedef typename functor_trait::functor_type functor_type; - typedef adaptor_functor adaptor_type; -}; - -// Doxygen (at least version 1.8.4) removes blank lines in a code block. -// That's why there are empty comment lines in the following code block. -/** Base type for adaptors. - * sigc::adapts wraps adaptors, functors, function pointers and class methods. - * It contains a single member functor which is always a sigc::adaptor_base. - * The typedef adaptor_type defines the exact type that is used - * to store the adaptor, functor, function pointer or class method passed - * into the constructor. It differs from @a T_functor unless @a T_functor - * inherits from sigc::adaptor_base. - * - * @par Example of a simple adaptor: - * @code - * namespace my_ns - * { - * template - * struct my_adaptor : public sigc::adapts - * { - * template - * struct deduce_result_type - * { typedef sigc::deduce_result_t type; }; - * typedef typename sigc::functor_trait::result_type result_type; - * // - * result_type - * operator()() const; - * // - * template - * typename deduce_result_type::type - * operator()(T_arg1 _A_arg1) const; - * // - * template - * typename deduce_result_type::type - * operator()(T_arg1 _A_arg1, T_arg2 _A_arg2) const; - * // - * // Constructs a my_adaptor object that wraps the passed functor. - * // Initializes adapts::functor_, which is invoked from operator()(). - * explicit my_adaptor(const T_functor& _A_functor) - * : sigc::adapts(_A_functor) {} - * }; - * } // end namespace my_ns - * // - * // Specialization of sigc::visitor for my_adaptor. - * namespace sigc - * { - * template - * struct visitor > - * { - * template - * static void do_visit_each(const T_action& _A_action, - * const my_ns::my_adaptor& _A_target) - * { - * sigc::visit_each(_A_action, _A_target.functor_); - * } - * }; - * } // end namespace sigc - * @endcode - * - * If you implement your own adaptor, you must also provide your specialization - * of sigc::visitor<>::do_visit_each<>() that will forward the call to the functor(s) - * your adapter is wrapping. Otherwise, pointers stored within the functor won't be - * invalidated when a sigc::trackable object is destroyed and you can end up - * executing callbacks on destroyed objects. - * - * Your specialization of sigc::visitor<> must be in namespace sigc. - * - * @ingroup adaptors - */ -template -struct adapts : public adaptor_base -{ - typedef typename adaptor_trait::result_type result_type; - typedef typename adaptor_trait::adaptor_type adaptor_type; - - /** Constructs an adaptor that wraps the passed functor. - * @param _A_functor Functor to invoke from operator()(). - */ - explicit adapts(const T_functor& _A_functor) - : functor_(_A_functor) - {} - - /// Adaptor that is invoked from operator()(). - mutable adaptor_type functor_; -}; - -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/bind.h.m4 b/sigc++/adaptors/macros/bind.h.m4 deleted file mode 100644 index 495f7fb3..00000000 --- a/sigc++/adaptors/macros/bind.h.m4 +++ /dev/null @@ -1,417 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([ORDINAL],[dnl -$1[]ifelse($1,1,[st],$1,2,[nd],$1,3,[rd],[th])[]dnl -]) -define([DEDUCE_RESULT_TYPE_COUNT],[dnl - template - struct deduce_result_type_internal - { typedef typename adaptor_type::template deduce_result_type::type), $1))>::type type; }; -]) -define([BIND_OPERATOR_LOCATION],[dnl -ifelse($2,1,,[dnl - /** Invokes the wrapped functor passing on the arguments. - * bound_ is passed as the ORDINAL($1) argument.dnl -FOR(1, eval($2-1),[ - * @param _A_arg%1 Argument to be passed on to the functor.]) - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_arg%1,eval($2-1))) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES::type), FOR($1,eval($2-1),[_P_(T_arg%1),]))> - (LIST(LOOP(_A_arg%1,eval($1-1)), bound_.invoke(), FOR($1,eval($2-1),[_A_arg%1,]))); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_arg%1,eval($2-1))) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES::type), FOR($1,eval($2-1),[_P_(T_arg%1),]))> - (LIST(LOOP(_A_arg%1,eval($1-1)), bound_.invoke(), FOR($1,eval($2-1),[_A_arg%1,]))); - } - #endif - -])dnl -]) -define([BIND_OPERATOR_COUNT],[dnl - /** Invokes the wrapped functor passing on the arguments. - * The last $1 argument(s) are fixed.dnl -FOR(1, eval($2-1),[ - * @param _A_arg%1 Argument to be passed on to the functor.]) - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_arg%1, eval($2-1))) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES::type), $1))> - (LIST(LOOP(_A_arg%1,eval($2-1)), LOOP(bound%1_.invoke(), $1))); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_arg%1, eval($2-1))) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES::type), $1))> - (LIST(LOOP(_A_arg%1,eval($2-1)), LOOP(bound%1_.invoke(), $1))); - } - #endif - -]) -define([BIND_FUNCTOR_LOCATION],[dnl -ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first template specialization in the documentation. ($1 = 0..CALL_SIZE-1) -/** Adaptor that binds an argument to the wrapped functor. - * This template specialization fixes the ORDINAL(eval($1+1)) argument of the wrapped functor. - * - * @ingroup bind - */ -template -struct bind_functor<$1, T_functor, T_bound, LIST(LOOP(nil, CALL_SIZE - 1))> : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - -ifelse($1,0,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type::type), FOR(eval($1+1),eval(CALL_SIZE-1),[_P_(T_arg%1),]))>::type type; }; -ifelse($1,0,[#endif -],)dnl - typedef typename adaptor_type::result_type result_type; - - /** Invokes the wrapped functor passing on the bound argument only. - * @return The return value of the functor invocation. - */ - result_type - operator()() - { - //Note: The AIX compiler sometimes gives linker errors if we do not define this in the class. - return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES<_P_(typename unwrap_reference::type)> (bound_.invoke()); - } - -FOR(eval($1+1),CALL_SIZE,[[BIND_OPERATOR_LOCATION(eval($1+1),%1)]])dnl - /** Constructs a bind_functor object that binds an argument to the passed functor. - * @param _A_func Functor to invoke from operator()(). - * @param _A_bound Argument to bind to the functor. - */ - bind_functor(_R_(T_functor) _A_func, _R_(T_bound) _A_bound) - : adapts(_A_func), bound_(_A_bound) - {} - - /// The argument bound to the functor. - bound_argument bound_; -}; -ifelse($1,eval(CALL_SIZE-1),[#endif // DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first template specialization in the documentation. ($1 = 0..CALL_SIZE-1) - -])dnl end BIND_FUNCTOR_LOCATION - -define([BIND_FUNCTOR_COUNT],[dnl -/** Adaptor that binds $1 argument(s) to the wrapped functor. - * This template specialization fixes the last $1 argument(s) of the wrapped functor. - * - * @ingroup bind - */ -template -struct bind_functor : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - -ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl - template - struct deduce_result_type_internal - { typedef typename adaptor_type::template deduce_result_type::type), $1))>::type type; }; -FOR(eval($1+1),eval(CALL_SIZE-1),[[DEDUCE_RESULT_TYPE_COUNT($1,%1)]])dnl - - template - struct deduce_result_type { - typedef typename deduce_result_type_internal::value, - LOOP(T_arg%1, eval(CALL_SIZE))>::type type; - }; -ifelse($1,1,[#endif // DOXYGEN_SHOULD_SKIP_THIS -],)dnl - typedef typename adaptor_type::result_type result_type; - - /** Invokes the wrapped functor passing on the bound argument only. - * @return The return value of the functor invocation. - */ - result_type - operator()() - { - //Note: The AIX compiler sometimes gives linker errors if we do not define this in the class. - return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES::type), $1)> (LOOP(bound%1_.invoke(), $1)); - } - -FOR(2,eval(CALL_SIZE-$1+1),[[BIND_OPERATOR_COUNT($1,%1)]])dnl - /** Constructs a bind_functor object that binds an argument to the passed functor. - * @param _A_func Functor to invoke from operator()().dnl -FOR(1,$1,[ - * @param _A_bound%1 Argument to bind to the functor.]) - */ - bind_functor(_R_(T_functor) _A_func, LOOP(_R_(T_type%1) _A_bound%1, $1)) - : adapts(_A_func), LOOP(bound%1_(_A_bound%1), $1) - {} - - /// The argument bound to the functor.dnl -FOR(1,$1,[ - bound_argument bound%1_;]) -}; - -ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first template specialization of bind_functor and no -dnl template specialization of visitor in the documentation. ($1 = 1..CALL_SIZE) -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::bind_functor performs a functor on the - * functor and on the object instances stored in the sigc::bind_functor object. - * - * @ingroup bind - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const bind_functor<-1, T_functor, LOOP(T_type%1, $1)>& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_);dnl -FOR(1,$1,[ - sigc::visit_each(_A_action, _A_target.bound%1_);]) - } -}; -ifelse($1,CALL_SIZE,[#endif // DOXYGEN_SHOULD_SKIP_THIS -],)dnl - -])dnl end BIND_FUNCTOR_COUNT - -define([BIND_COUNT],[dnl -/** Creates an adaptor of type sigc::bind_functor which fixes the last $1 argument(s) of the passed functor. - * This function overload fixes the last $1 argument(s) of @e _A_func. - * - * @param _A_func Functor that should be wrapped.dnl -FOR(1,$1,[ - * @param _A_b%1 Argument to bind to @e _A_func.]) - * @return Adaptor that executes _A_func with the bound argument on invokation. - * - * @ingroup bind - */ -template -inline bind_functor<-1, T_functor,dnl -FOR(1,eval($1-1),[ - T_type%1,]) - T_type$1> -bind(const T_functor& _A_func, LOOP(T_type%1 _A_b%1, $1)) -{ return bind_functor<-1, T_functor,dnl -FOR(1,eval($1-1),[ - T_type%1,]) - T_type$1> - (_A_func, LOOP(_A_b%1, $1)); -} - -]) - -divert(0)dnl -_FIREWALL([ADAPTORS_BIND]) -#include -#include - -//TODO: See comment in functor_trait.h. -#if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO) - #define SIGC_NIL_HAS_BEEN_PUSHED 1 - #pragma push_macro("nil") - #undef nil -#endif - -namespace sigc { - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - -namespace internal { - -template -struct count_void - { static const int value=0; }; -template -struct count_void - { static const int value=1; }; -template -struct count_void - { static const int value=2; }; -template -struct count_void - { static const int value=3; }; -template -struct count_void - { static const int value=4; }; -template -struct count_void - { static const int value=5; }; -template -struct count_void - { static const int value=6; }; -template <> -struct count_void - { static const int value=7; }; - -} /* namespace internal */ - -#endif /*DOXYGEN_SHOULD_SKIP_THIS*/ - - -/** @defgroup bind bind(), bind_return() - * sigc::bind() alters an arbitrary functor by fixing arguments to certain values. - * Up to CALL_SIZE arguments can be bound at a time. - * For single argument binding, overloads of sigc::bind() are provided that let you - * specify the zero-based position of the argument to fix with the first template parameter. - * (A value of @p -1 fixes the last argument so sigc::bind<-1>() gives the same result as sigc::bind().) - * The types of the arguments can optionally be specified if not deduced. - * - * @par Examples: - * @code - * void foo(int, int, int); - * // single argument binding ... - * sigc::bind(&foo,1)(2,3); //fixes the last (third) argument and calls foo(2,3,1) - * sigc::bind<-1>(&foo,1)(2,3); //same as bind(&foo,1)(2,3) (calls foo(2,3,1)) - * sigc::bind<0>(&foo,1)(2,3); //fixes the first argument and calls foo(1,2,3) - * sigc::bind<1>(&foo,1)(2,3); //fixes the second argument and calls foo(2,1,3) - * sigc::bind<2>(&foo,1)(2,3); //fixes the third argument and calls foo(2,3,1) - * // multi argument binding ... - * sigc::bind(&foo,1,2)(3); //fixes the last two arguments and calls foo(3,1,2) - * sigc::bind(&foo,1,2,3)(); //fixes all three arguments and calls foo(1,2,3) - * @endcode - * - * The functor sigc::bind() returns can be passed into - * sigc::signal::connect() directly. - * - * @par Example: - * @code - * sigc::signal some_signal; - * void foo(int); - * some_signal.connect(sigc::bind(&foo,1)); - * @endcode - * - * sigc::bind_return() alters an arbitrary functor by - * fixing its return value to a certain value. - * - * @par Example: - * @code - * void foo(); - * std::cout << sigc::bind_return(&foo, 5)(); // calls foo() and returns 5 - * @endcode - * - * You can bind references to functors by passing the objects through - * the sigc::ref() helper function. - * - * @par Example: - * @code - * int some_int; - * sigc::signal some_signal; - * void foo(int&); - * some_signal.connect(sigc::bind(&foo,sigc::ref(some_int))); - * @endcode - * - * If you bind an object of a sigc::trackable derived type to a functor - * by reference, a slot assigned to the bind adaptor is cleared automatically - * when the object goes out of scope. - * - * @par Example: - * @code - * struct bar : public sigc::trackable {} some_bar; - * sigc::signal some_signal; - * void foo(bar&); - * some_signal.connect(sigc::bind(&foo,sigc::ref(some_bar))); - * // disconnected automatically if some_bar goes out of scope - * @endcode - * - * @ingroup adaptors - */ - -/** Adaptor that binds an argument to the wrapped functor. - * Use the convenience function sigc::bind() to create an instance of sigc::bind_functor. - * - * The following template arguments are used: - * - @e I_location Zero-based position of the argument to fix (@p -1 for the last argument).dnl -FOR(1, CALL_SIZE,[ - * - @e T_type%1 Type of the [ORDINAL(%1)] bound argument.]) - * - @e T_functor Type of the functor to wrap. - * - * @ingroup bind - */ -template -#ifndef DOXYGEN_SHOULD_SKIP_THIS -struct bind_functor; -#else -struct bind_functor {}; -#endif - -FOR(0,eval(CALL_SIZE-1),[[BIND_FUNCTOR_LOCATION(%1)]])dnl - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::bind_functor performs a functor on the - * functor and on the object instances stored in the sigc::bind_functor object. - * - * @ingroup bind - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const bind_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - sigc::visit_each(_A_action, _A_target.bound_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -FOR(1,CALL_SIZE,[[BIND_FUNCTOR_COUNT(%1)]])dnl - -/** Creates an adaptor of type sigc::bind_functor which binds the passed argument to the passed functor. - * The optional template argument @e I_location specifies the zero-based - * position of the argument to be fixed (@p -1 stands for the last argument). - * - * @param _A_func Functor that should be wrapped. - * @param _A_b1 Argument to bind to @e _A_func. - * @return Adaptor that executes @e _A_func with the bound argument on invokation. - * - * @ingroup bind - */ -template -inline bind_functor -bind(const T_functor& _A_func, T_bound1 _A_b1) -{ - return bind_functor - (_A_func, _A_b1); -} - -FOR(1,CALL_SIZE,[[BIND_COUNT(%1)]])dnl - -} /* namespace sigc */ - -#ifdef SIGC_NIL_HAS_BEEN_PUSHED - #undef SIGC_NIL_HAS_BEEN_PUSHED - #pragma pop_macro("nil") -#endif diff --git a/sigc++/adaptors/macros/bind_return.h.m4 b/sigc++/adaptors/macros/bind_return.h.m4 deleted file mode 100644 index 177e7612..00000000 --- a/sigc++/adaptors/macros/bind_return.h.m4 +++ /dev/null @@ -1,126 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([BIND_RETURN_OPERATOR],[dnl - /** Invokes the wrapped functor passing on the arguments.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the functor.]) - * @return The fixed return value. - */ - template - inline typename unwrap_reference::type operator()(LOOP(T_arg%1 _A_a%1, $1)) - { this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1)); return ret_value_.invoke(); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - inline typename unwrap_reference::type sun_forte_workaround(LOOP(T_arg%1 _A_a%1, $1)) - { this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1)); return ret_value_.invoke(); - } - #endif - -]) - -divert(0)dnl -_FIREWALL([ADAPTORS_BIND_RETURN]) -#include -#include - -namespace sigc { - -/** Adaptor that fixes the return value of the wrapped functor. - * Use the convenience function sigc::bind_return() to create an instance of sigc::bind_return_functor. - * - * The following template arguments are used: - * - @e T_return Type of the fixed return value. - * - @e T_functor Type of the functor to wrap. - * - * @ingroup bind - */ -template -struct bind_return_functor : public adapts -{ -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename unwrap_reference::type type; }; -#endif - typedef typename unwrap_reference::type result_type; - - /** Invokes the wrapped functor dropping its return value. - * @return The fixed return value. - */ - typename unwrap_reference::type operator()(); - -FOR(1,CALL_SIZE,[[BIND_RETURN_OPERATOR(%1)]])dnl - - /** Constructs a bind_return_functor object that fixes the return value to @p _A_ret_value. - * @param _A_functor Functor to invoke from operator()(). - * @param _A_ret_value Value to return from operator()(). - */ - bind_return_functor(_R_(T_functor) _A_functor, _R_(T_return) _A_ret_value) - : adapts(_A_functor), ret_value_(_A_ret_value) - {} - - /// The fixed return value. - bound_argument ret_value_; // public, so that visit_each() can access it -}; - -template -typename unwrap_reference::type bind_return_functor::operator()() - { this->functor_(); return ret_value_.invoke(); } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::bind_return_functor performs a functor on the - * functor and on the object instance stored in the sigc::bind_return_functor object. - * - * @ingroup bind - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const bind_return_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.ret_value_); - sigc::visit_each(_A_action, _A_target.functor_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Creates an adaptor of type sigc::bind_return_functor which fixes the return value of the passed functor to the passed argument. - * - * @param _A_functor Functor that should be wrapped. - * @param _A_ret_value Argument to fix the return value of @e _A_functor to. - * @return Adaptor that executes @e _A_functor on invokation and returns @e _A_ret_value. - * - * @ingroup bind - */ -template -inline bind_return_functor -bind_return(const T_functor& _A_functor, T_return _A_ret_value) -{ return bind_return_functor(_A_functor, _A_ret_value); } - -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/compose.h.m4 b/sigc++/adaptors/macros/compose.h.m4 deleted file mode 100644 index 6cd10dbc..00000000 --- a/sigc++/adaptors/macros/compose.h.m4 +++ /dev/null @@ -1,240 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([COMPOSE1_OPERATOR],[dnl - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_a%1, $1)) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES> - (get_(LOOP(_A_a%1, $1))); - } - -]) - -define([COMPOSE2_OPERATOR],[dnl - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_a%1, $1)) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES, - sigc::deduce_result_t> - (get1_(LOOP(_A_a%1, $1)), get2_(LOOP(_A_a%1,$1))); - } - -]) - -divert(0) -_FIREWALL([ADAPTORS_COMPOSE]) -#include - -namespace sigc { - -/** @defgroup compose compose() - * sigc::compose() combines two or three arbitrary functors. - * On invokation, parameters are passed on to one or two getter functor(s). - * The return value(s) are then passed on to the setter function. - * - * @par Examples: - * @code - * float square_root(float a) { return sqrtf(a); } - * float sum(float a, float b) { return a+b; } - * std::cout << sigc::compose(&square_root, &sum)(9, 16); // calls square_root(sum(3,6)) - * std::cout << sigc::compose(&sum, &square_root, &square_root)(9); // calls sum(square_root(9), square_root(9)) - * @endcode - * - * The functor sigc::compose() returns can be passed directly into - * sigc::signal::connect(). - * - * @par Example: - * @code - * sigc::signal some_signal; - * some_signal.connect(sigc::compose(&square_root, &sum)); - * @endcode - * - * @ingroup adaptors - */ - -/** Adaptor that combines two functors. - * Use the convenience function sigc::compose() to create an instance of sigc::compose1_functor. - * - * The following template arguments are used: - * - @e T_setter Type of the setter functor to wrap. - * - @e T_getter Type of the getter functor to wrap. - * - * @ingroup compose - */ -template -struct compose1_functor : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - typedef T_setter setter_type; - typedef T_getter getter_type; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type< - sigc::deduce_result_t - >::type type; }; -#endif - typedef typename adaptor_type::result_type result_type; - - result_type - operator()(); - -FOR(1,CALL_SIZE, [[COMPOSE1_OPERATOR(%1)]])dnl - - /** Constructs a compose1_functor object that combines the passed functors. - * @param _A_setter Functor that receives the return values of the invokation of @e _A_getter1 and @e _A_getter2. - * @param _A_getter Functor to invoke from operator()(). - */ - compose1_functor(const T_setter& _A_setter, const T_getter& _A_getter) - : adapts(_A_setter), get_(_A_getter) - {} - - getter_type get_; // public, so that visit_each() can access it -}; - -template -typename compose1_functor::result_type -compose1_functor::operator()() - { return this->functor_(get_()); } - -/** Adaptor that combines three functors. - * Use the convenience function sigc::compose() to create an instance of sigc::compose2_functor. - * - * The following template arguments are used: - * - @e T_setter Type of the setter functor to wrap. - * - @e T_getter1 Type of the first getter functor to wrap. - * - @e T_getter2 Type of the second getter functor to wrap. - * - * @ingroup compose - */ -template -struct compose2_functor : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - typedef T_setter setter_type; - typedef T_getter1 getter1_type; - typedef T_getter2 getter2_type; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type< - typename sigc::deduce_result_t, - typename sigc::deduce_result_t - >::type result_type; }; -#endif - typedef typename adaptor_type::result_type result_type; - - result_type - operator()(); - -FOR(1,CALL_SIZE,[[COMPOSE2_OPERATOR(%1)]])dnl - - /** Constructs a compose2_functor object that combines the passed functors. - * @param _A_setter Functor that receives the return values of the invokation of @e _A_getter1 and @e _A_getter2. - * @param _A_getter1 Functor to invoke from operator()(). - * @param _A_getter2 Functor to invoke from operator()(). - */ - compose2_functor(const T_setter& _A_setter, - const T_getter1& _A_getter1, - const T_getter2& _A_getter2) - : adapts(_A_setter), get1_(_A_getter1), get2_(_A_getter2) - {} - - getter1_type get1_; // public, so that visit_each() can access it - getter2_type get2_; // public, so that visit_each() can access it -}; - -template -typename compose2_functor::result_type -compose2_functor::operator()() - { return this->functor_(get1_(), get2_()); } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::compose1_functor performs a functor on the - * functors stored in the sigc::compose1_functor object. - * - * @ingroup compose - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const compose1_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - sigc::visit_each(_A_action, _A_target.get_); - } -}; - -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::compose2_functor performs a functor on the - * functors stored in the sigc::compose2_functor object. - * - * @ingroup compose - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const compose2_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - sigc::visit_each(_A_action, _A_target.get1_); - sigc::visit_each(_A_action, _A_target.get2_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Creates an adaptor of type sigc::compose1_functor which combines two functors. - * - * @param _A_setter Functor that receives the return value of the invokation of @e _A_getter. - * @param _A_getter Functor to invoke from operator()(). - * @return Adaptor that executes @e _A_setter with the value returned from invokation of @e _A_getter. - * - * @ingroup compose - */ -template -inline compose1_functor -compose(const T_setter& _A_setter, const T_getter& _A_getter) - { return compose1_functor(_A_setter, _A_getter); } - -/** Creates an adaptor of type sigc::compose2_functor which combines three functors. - * - * @param _A_setter Functor that receives the return values of the invokation of @e _A_getter1 and @e _A_getter2. - * @param _A_getter1 Functor to invoke from operator()(). - * @param _A_getter2 Functor to invoke from operator()(). - * @return Adaptor that executes @e _A_setter with the values return from invokation of @e _A_getter1 and @e _A_getter2. - * - * @ingroup compose - */ -template -inline compose2_functor -compose(const T_setter& _A_setter, const T_getter1& _A_getter1, const T_getter2& _A_getter2) - { return compose2_functor(_A_setter, _A_getter1, _A_getter2); } - -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/deduce_result_type.h.m4 b/sigc++/adaptors/macros/deduce_result_type.h.m4 deleted file mode 100644 index c7c8fca9..00000000 --- a/sigc++/adaptors/macros/deduce_result_type.h.m4 +++ /dev/null @@ -1,91 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) -include(template.macros.m4) - -divert(0)dnl -/* -*/ -_FIREWALL([ADAPTORS_DEDUCE_RESULT_TYPE]) -#include - -namespace sigc { - -/** A hint to the compiler. - * Functors which have all methods based on templates - * should publicly inherit from this hint and define - * a nested template class @p deduce_result_type that - * can be used to deduce the methods' return types. - * - * adaptor_base inherits from the functor_base hint so - * derived types should also have a result_type defined. - * - * Adaptors don't inherit from this type directly. They use - * use sigc::adapts as a base type instead. sigc::adaptors - * wraps arbitrary functor types as well as function pointers - * and class methods. - * - * @ingroup adaptors - */ -struct adaptor_base : public functor_base {}; - - -/** Deduce the return type of a functor. - * typename deduce_result_type::type - * deduces a functor's result type if @p functor_type inherits from - * sigc::functor_base and defines @p result_type or if @p functor_type - * is actually a (member) function type. Multi-type functors are not - * supported. - * - * sigc++ adaptors use - * typename deduce_result_type::type - * to determine the return type of their templated operator() overloads. - * - * Adaptors in turn define a nested template class @p deduce_result_type - * that is used by template specializations of the global deduce_result_type - * template to correctly deduce the return types of the adaptor's suitable - * template operator() overload. - * - * @ingroup adaptors - */ -template -struct deduce_result_type -{ - //The compiler will choose this method overload if T_functor derives from adaptor_base, - //and if it has its own deduce_result_type member (which has its own ::type member). - template::type> - static - typename U_functor::template deduce_result_type::type - test(); - - //Otherwise, the compiler will choose this fallback method. - template - static - typename functor_trait::result_type - test(); - - using type = decltype (test ()); -}; - -template -using deduce_result_t = typename deduce_result_type::type; - -dnl #ifdef SIGC_CXX_TYPEOF -dnl FOR(0,CALL_SIZE,[[DEDUCE_RESULT_TYPE_TYPEOF(%1,CALL_SIZE)]]) -dnl #endif -dnl -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/exception_catch.h.m4 b/sigc++/adaptors/macros/exception_catch.h.m4 deleted file mode 100644 index 5f5cd109..00000000 --- a/sigc++/adaptors/macros/exception_catch.h.m4 +++ /dev/null @@ -1,183 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([EXCEPTION_CATCH_OPERATOR],[dnl - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_a%1, $1)) - { - try - { - return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1)); - } - catch (...) - { return catcher_(); } - } - -]) - -divert(0)dnl -_FIREWALL([ADAPTORS_EXCEPTION_CATCH]) -#include - -namespace sigc { - -/* - functor adaptor: exception_catch(functor, catcher) - - usage: - - - Future directions: - The catcher should be told what type of return it needs to - return for multiple type functors, to do this the user - will need to derive from catcher_base. -*/ -/** @defgroup exception_catch exception_catch() - * sigc::exception_catch() catches an exception thrown from within - * the wrapped functor and directs it to a catcher functor. - * This catcher can then rethrow the exception and catch it with the proper type. - * - * Note that the catcher is expected to return the same type - * as the wrapped functor so that normal flow can continue. - * - * Catchers can be cascaded to catch multiple types, because uncaught - * rethrown exceptions proceed to the next catcher adaptor. - * - * @par Examples: - * @code - * struct my_catch - * { - * int operator()() - * { - * try { throw; } - * catch (std::range_error e) // catch what types we know - * { std::cerr << "caught " << e.what() << std::endl; } - * return 1; - * } - * } - * int foo(); // throws std::range_error - * sigc::exception_catch(&foo, my_catch())(); - * @endcode - * - * The functor sigc::exception_catch() returns can be directly passed into - * sigc::signal::connect(). - * - * @par Example: - * @code - * sigc::signal some_signal; - * some_signal.connect(sigc::exception_catch(&foo, my_catch)); - * @endcode - * - * @ingroup adaptors - */ - -template ::result_type> -struct exception_catch_functor : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type::type type; }; -#endif - typedef T_return result_type; - - result_type - operator()(); - -FOR(1,CALL_SIZE,[[EXCEPTION_CATCH_OPERATOR(%1)]])dnl - exception_catch_functor(const T_functor& _A_func, - const T_catcher& _A_catcher) - : adapts(_A_func), catcher_(_A_catcher) - {} - - T_catcher catcher_; -}; - -template -typename exception_catch_functor::result_type -exception_catch_functor::operator()() - { - try - { return this->functor_(); } - catch (...) - { return catcher_(); } - } - -// void specialization -template -struct exception_catch_functor : public adapts -{ - typedef void result_type; - typedef typename adapts::adaptor_type adaptor_type; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type::type type; }; -#endif - - void - operator()(); - -FOR(1,CALL_SIZE,[[EXCEPTION_CATCH_OPERATOR(%1)]])dnl - exception_catch_functor() {} - exception_catch_functor(const T_functor& _A_func, - const T_catcher& _A_catcher) - : adapts(_A_func), catcher_(_A_catcher) - {} - ~exception_catch_functor() {} - - T_catcher catcher_; -}; - -template -void exception_catch_functor::operator()() - { - try - { this->functor_(); } // I don't understand why void return doesn't work here (Martin) - catch (...) - { this->catcher_(); } - } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const exception_catch_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - sigc::visit_each(_A_action, _A_target.catcher_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -template -inline exception_catch_functor -exception_catch(const T_functor& _A_func, const T_catcher& _A_catcher) - { return exception_catch_functor(_A_func, _A_catcher); } - -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/hide.h.m4 b/sigc++/adaptors/macros/hide.h.m4 deleted file mode 100644 index 6bdc199e..00000000 --- a/sigc++/adaptors/macros/hide.h.m4 +++ /dev/null @@ -1,251 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([ORDINAL],[dnl -ifelse($1,0,,$1)ifelse($1,0,[last],$1,1,[st],$1,2,[nd],$1,3,[rd],[th])[]dnl -]) -define([DEDUCE_RESULT_TYPE],[dnl -ifelse(eval($1 < 2),1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl Only for the first two template specializations. ($1 = 0..CALL_SIZE) - template - struct deduce_result_type -ifelse($1,0,[dnl - { typedef typename adaptor_type::template deduce_result_type::type type; }; -],[dnl - { typedef typename adaptor_type::template deduce_result_type::type type; }; -])dnl -ifelse(eval($1 < 2),1,[#endif // DOXYGEN_SHOULD_SKIP_THIS -],)dnl -]) -define([HIDE_OPERATOR],[dnl -ifelse($2,0,,[dnl -ifelse($2,1,[dnl - /** Invokes the wrapped functor ignoring the only argument. - * @param _A_a1 Argument to be ignored. - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(T_arg1) - { return this->functor_(); } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(T_arg1 _A_a1) - { return this->functor_(); } - #endif - -],$1,0,[dnl - /** Invokes the wrapped functor, ignoring the last argument.dnl -FOR(1, eval($2-1),[ - * @param _A_a%1 Argument to be passed on to the functor.]) - * @param _A_a$2 Argument to be ignored. - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_a%1, eval($2-1)), T_arg$2) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LIST(FOR(1,eval($2-1),[_A_a%1,]))); } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_a%1, eval($2-1)), T_arg$2) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LIST(FOR(1,eval($2-1),[_A_a%1,]))); } - #endif - -],[dnl - /** Invokes the wrapped functor, ignoring the ORDINAL($1) argument.dnl -FOR(1, eval($1-1),[ - * @param _A_a%1 Argument to be passed on to the functor.]) - * @param _A_a$1 Argument to be ignored.dnl -FOR(eval($1+1), $2,[ - * @param _A_a%1 Argument to be passed on to the functor.]) - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(LIST(FOR(1,eval($1-1),[T_arg%1 _A_a%1,]),T_arg$1,FOR(eval($1+1),$2,[T_arg%1 _A_a%1,]))) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LIST(FOR(1,eval($1-1),[_A_a%1,]),FOR(eval($1+1),$2,[_A_a%1,]))); } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LIST(FOR(1,eval($1-1),[T_arg%1 _A_a%1,]),T_arg$1,FOR(eval($1+1),$2,[T_arg%1 _A_a%1,]))) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LIST(FOR(1,eval($1-1),[_A_a%1,]),FOR(eval($1+1),$2,[_A_a%1,]))); } - #endif - -])])dnl -])dnl end HIDE_OPERATOR - -define([HIDE_FUNCTOR],[dnl -ifelse($1,1,[#ifndef DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first two template specializations in the documentation. ($1 = -1..CALL_SIZE-1) -/** Adaptor that adds a dummy parameter to the wrapped functor. - * This template specialization ignores the value of the ORDINAL(eval($1+1)) parameter in operator()(). - * - * @ingroup hide - */ -template -struct hide_functor <$1, T_functor> : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - -DEDUCE_RESULT_TYPE(eval($1+1),CALL_SIZE)dnl - typedef typename adaptor_type::result_type result_type; - -FOR(eval($1+1),CALL_SIZE,[[HIDE_OPERATOR(eval($1+1),%1)]])dnl - - /** Constructs a hide_functor object that adds a dummy parameter to the passed functor. - * @param _A_func Functor to invoke from operator()(). - */ - explicit hide_functor(const T_functor& _A_func) - : adapts(_A_func) - {} -}; -ifelse($1,eval(CALL_SIZE-1),[#endif // DOXYGEN_SHOULD_SKIP_THIS -],)dnl Include only the first two template specializations in the documentation. ($1 = -1..CALL_SIZE-1) - -])dnl end HIDE_FUNCTOR - -divert(0)dnl -_FIREWALL([ADAPTORS_HIDE]) -#include - -namespace sigc { - -/** @defgroup hide hide(), hide_return() - * sigc::hide() alters an arbitrary functor in that it adds a parameter - * whose value is ignored on invocation of the returned functor. - * Thus you can discard one argument of a signal. - * - * You may optionally specify the zero-based position of the parameter - * to ignore as a template argument. The default is to ignore the last - * parameter. - * (A value of @p -1 adds a parameter at the end so sigc::hide<-1>() gives the same result as sigc::hide().) - * - * The type of the parameter can optionally be specified if not deduced. - * - * @par Examples: - * @code - * void foo(int, int); - * // single argument hiding ... - * sigc::hide(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2) - * sigc::hide<-1>(&foo)(1,2,3); // same as sigc::hide(&foo)(1,2,3) (calls foo(1,2)) - * sigc::hide<0>(&foo)(1,2,3); // adds a dummy parameter at the beginning and calls foo(2,3) - * sigc::hide<1>(&foo)(1,2,3); // adds a dummy parameter in the middle and calls foo(1,3) - * sigc::hide<2>(&foo)(1,2,3); // adds a dummy parameter at the back and calls foo(1,2) - * @endcode - * - * The functor sigc::hide() returns can be directly passed into - * sigc::signal::connect(). - * - * @par Example: - * @code - * sigc::signal some_signal; - * void foo(); - * some_signal.connect(sigc::hide(&foo)); - * @endcode - * - * sigc::hide() can be nested in order to discard multiple arguments. - * @par Example: - * @code - * // multiple argument hiding ... - * sigc::hide(sigc::hide(&foo))(1,2,3,4); // adds two dummy parameters at the back and calls foo(1,2) - * @endcode - - * sigc::hide_return() alters an arbitrary functor by - * dropping its return value, thus converting it to a void functor. - * - * @ingroup adaptors - */ - -/** Adaptor that adds a dummy parameter to the wrapped functor. - * Use the convenience function sigc::hide() to create an instance of sigc::hide_functor. - * - * The following template arguments are used: - * - @e I_location Zero-based position of the dummy parameter (@p -1 for the last parameter). - * - @e T_type Type of the dummy parameter. - * - @e T_functor Type of the functor to wrap. - * - * @ingroup hide - */ -template -#ifndef DOXYGEN_SHOULD_SKIP_THIS -struct hide_functor; -#else -struct hide_functor {}; -#endif - -FOR(-1,eval(CALL_SIZE-1),[[HIDE_FUNCTOR(%1)]])dnl - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::hide_functor performs a functor on the - * functor stored in the sigc::hide_functor object. - * - * @ingroup hide - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const hide_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Creates an adaptor of type sigc::hide_functor which adds a dummy parameter to the passed functor. - * The optional template argument @e I_location specifies the zero-based - * position of the dummy parameter in the returned functor (@p -1 stands for the last parameter). - * - * @param _A_func Functor that should be wrapped. - * @return Adaptor that executes @e _A_func, ignoring the value of the dummy parameter. - * - * @ingroup hide - */ -template -inline hide_functor -hide(const T_functor& _A_func) - { return hide_functor(_A_func); } - -/** Creates an adaptor of type sigc::hide_functor which adds a dummy parameter to the passed functor. - * This overload adds a dummy parameter at the back of the functor's parameter list. - * - * @param _A_func Functor that should be wrapped. - * @return Adaptor that executes @e _A_func, ignoring the value of the last parameter. - * - * @ingroup hide - */ -template -inline hide_functor<-1, T_functor> -hide(const T_functor& _A_func) - { return hide_functor<-1, T_functor> (_A_func); } - -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/retype.h.m4 b/sigc++/adaptors/macros/retype.h.m4 deleted file mode 100644 index 8267c81e..00000000 --- a/sigc++/adaptors/macros/retype.h.m4 +++ /dev/null @@ -1,222 +0,0 @@ -dnl Copyright 2003, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([RETYPE_OPERATOR],[dnl -ifelse($1,0,[dnl - result_type operator()(); - -],[dnl - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_a%1, $1)) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES, $1)> - (LOOP([[static_cast(_A_a%1)]], $1)); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_a%1, $1)) - { return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES, $1)> - (LOOP([[static_cast(_A_a%1)]], $1)); - } - #endif - -])dnl -]) -define([RETYPE_POINTER_FUNCTOR],[dnl -/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters passed on to the functor. - * This function template specialization works on sigc::pointer_functor. - * - * @param _A_functor Functor that should be wrapped. - * @return Adaptor that executes @e _A_functor performing C-style casts on the paramters passed on. - * - * @ingroup retype - */ -template -inline retype_functor, LOOP(T_arg%1, $1)) > -retype(const pointer_functor$1& _A_functor) -{ return retype_functor, LOOP(T_arg%1, $1)) > - (_A_functor); } - -]) -define([RETYPE_MEM_FUNCTOR],[dnl -/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters passed on to the functor. - * This function template specialization works on sigc::$2[]mem_functor. - * - * @param _A_functor Functor that should be wrapped. - * @return Adaptor that executes @e _A_functor performing C-style casts on the paramters passed on. - * - * @ingroup retype - */ -template -inline retype_functor, LOOP(T_arg%1, $1)) > -retype(const $2[]mem_functor$1& _A_functor) -{ return retype_functor, LOOP(T_arg%1, $1)) > - (_A_functor); } - -]) - -divert(0)dnl -_FIREWALL([ADAPTORS_RETYPE]) -#include -#include -#include -#include - -//TODO: See comment in functor_trait.h. -#if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO) - #define SIGC_NIL_HAS_BEEN_PUSHED 1 - #pragma push_macro("nil") - #undef nil -#endif - -namespace sigc { - -/** @defgroup retype retype(), retype_return() - * sigc::retype() alters a sigc::pointer_functor, a sigc::mem_functor or a sigc::slot - * in that it makes C-style casts to the functor's parameter types - * of all parameters passed through operator()(). - * - * Use this adaptor for inline conversion between numeric or other simple types. - * @par Example: - * @code - * void foo(int); - * sigc::retype(sigc::ptr_fun(&foo))(5.7F); // calls foo(5) - * @endcode - * - * The functor that sigc::retype() returns can be passed directly into - * sigc::signal::connect(). - * - * @par Example: - * @code - * sigc::signal some_signal; - * void foo(int); - * some_signal.connect(sigc::retype(sigc::ptr_fun(&foo))); - * @endcode - * - * This adaptor builds an exception in that it only works on sig::pointer_functor, - * sigc::mem_functor and sigc::slot because it needs sophisticated information about - * the parameter types that cannot be deduced from arbitrary functor types. - * - * sigc::retype_return() alters the return type of an arbitrary functor. - * Like in sigc::retype() a C-style cast is performed. Usage sigc::retype_return() is - * not restricted to libsigc++ functor types but you need to - * specify the new return type as a template parameter. - * - * @par Example: - * @code - * float foo(); - * std::cout << sigc::retype_return(&foo)(); // converts foo's return value to an integer - * @endcode - * - * @ingroup adaptors - */ - -/** Adaptor that performs C-style casts on the parameters passed on to the functor. - * Use the convenience function sigc::retype() to create an instance of retype_functor. - * - * The following template arguments are used: - * - @e T_functor Type of the functor to wrap.dnl -FOR(1, CALL_SIZE,[ - * - @e T_type%1 Type of @e T_functor's %1th argument.]) - * - * @ingroup retype - */ -template -struct retype_functor - : public adapts -{ - typedef typename adapts::adaptor_type adaptor_type; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type::type type; }; -#endif - typedef typename adapts::result_type result_type; - -FOR(0,CALL_SIZE,[[RETYPE_OPERATOR(%1)]])dnl - - /** Constructs a retype_functor object that performs C-style casts on the parameters passed on to the functor. - * @param _A_functor Functor to invoke from operator()(). - */ - explicit retype_functor(type_trait_take_t _A_functor) - : adapts(_A_functor) - {} -}; - -template -typename retype_functor::result_type -retype_functor::operator()() - { return this->functor_(); } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::retype_functor performs a functor on the - * functor stored in the sigc::retype_functor object. - * - * @ingroup retype - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const retype_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters passed on to the functor. - * This function template specialization works on sigc::slot. - * - * @param _A_functor Functor that should be wrapped. - * @return Adaptor that executes @e _A_functor performing C-style casts on the paramters passed on. - * - * @ingroup retype - */ -template -inline retype_functor, LOOP(T_arg%1, CALL_SIZE)) > -retype(const slot& _A_functor) -{ return retype_functor, LOOP(T_arg%1, CALL_SIZE)) > - (_A_functor); } - - -FOR(0,CALL_SIZE,[[RETYPE_POINTER_FUNCTOR(%1)]])dnl - -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[const_])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[volatile_])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[const_volatile_])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[bound_])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[bound_const_])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[bound_volatile_])]])dnl -FOR(0,CALL_SIZE,[[RETYPE_MEM_FUNCTOR(%1,[bound_const_volatile_])]])dnl - -} /* namespace sigc */ - -#ifdef SIGC_NIL_HAS_BEEN_PUSHED - #undef SIGC_NIL_HAS_BEEN_PUSHED - #pragma pop_macro("nil") -#endif diff --git a/sigc++/adaptors/macros/retype_return.h.m4 b/sigc++/adaptors/macros/retype_return.h.m4 deleted file mode 100644 index cf13b986..00000000 --- a/sigc++/adaptors/macros/retype_return.h.m4 +++ /dev/null @@ -1,173 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([RETYPE_RETURN_OPERATOR],[dnl - template - inline T_return operator()(LOOP(T_arg%1 _A_a%1, $1)) - { return T_return(this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1))); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - inline T_return sun_forte_workaround(LOOP(T_arg%1 _A_a%1, $1)) - { return T_return(this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1))); - } - #endif - -]) -define([RETYPE_RETURN_VOID_OPERATOR],[dnl - template - inline void operator()(LOOP(T_arg%1 _A_a%1, $1)) - { this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1)); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - inline void sun_forte_workaround(LOOP(T_arg%1 _A_a%1, $1)) - { this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_a%1, $1)); - } - #endif - -]) - -divert(0)dnl -_FIREWALL([ADAPTORS_RETYPE_RETURN]) -#include - -namespace sigc { - -/** Adaptor that performs a C-style cast on the return value of a functor. - * Use the convenience function sigc::retype_return() to create an instance of retype_return_functor. - * - * The following template arguments are used: - * - @e T_return Target type of the C-style cast. - * - @e T_functor Type of the functor to wrap. - * - * @ingroup retype - */ -template -struct retype_return_functor : public adapts -{ -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef T_return type; }; -#endif - typedef T_return result_type; - - T_return operator()(); - -FOR(1,CALL_SIZE,[[RETYPE_RETURN_OPERATOR(%1)]])dnl - retype_return_functor() {} - - /** Constructs a retype_return_functor object that perform a C-style cast on the return value of the passed functor. - * @param _A_functor Functor to invoke from operator()(). - */ - explicit retype_return_functor(_R_(T_functor) _A_functor) - : adapts(_A_functor) - {} -}; - -template -T_return retype_return_functor::operator()() - { return T_return(this->functor_()); } - - -/** Adaptor that performs a C-style cast on the return value of a functor. - * This template specialization is for a void return. It drops the return value of the functor it invokes. - * Use the convenience function sigc::hide_return() to create an instance of sigc::retype_return_functor. - * - * @ingroup retype - */ -/* The void specialization is needed because of explicit cast to T_return. - */ -template -struct retype_return_functor : public adapts -{ -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef void type; }; -#endif - typedef void result_type; - - void operator()(); - -FOR(1,CALL_SIZE,[[RETYPE_RETURN_VOID_OPERATOR(%1)]])dnl - retype_return_functor() {} - retype_return_functor(_R_(T_functor) _A_functor) - : adapts(_A_functor) - {} -}; - -template -void retype_return_functor::operator()() - { this->functor_(); } - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::retype_return_functor performs a functor on the - * functor stored in the sigc::retype_return_functor object. - * - * @ingroup retype - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const retype_return_functor& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Creates an adaptor of type sigc::retype_return_functor which performs a C-style cast on the return value of the passed functor. - * The template argument @e T_return specifies the target type of the cast. - * - * @param _A_functor Functor that should be wrapped. - * @return Adaptor that executes @e _A_functor performing a C-style cast on the return value. - * - * @ingroup retype - */ -template -inline retype_return_functor -retype_return(const T_functor& _A_functor) - { return retype_return_functor(_A_functor); } - -/** Creates an adaptor of type sigc::retype_return_functor which drops the return value of the passed functor. - * - * @param _A_functor Functor that should be wrapped. - * @return Adaptor that executes @e _A_functor dropping its return value. - * - * @ingroup hide - */ -template -inline retype_return_functor -hide_return(const T_functor& _A_functor) - { return retype_return_functor(_A_functor); } - -} /* namespace sigc */ diff --git a/sigc++/adaptors/macros/track_obj.h.m4 b/sigc++/adaptors/macros/track_obj.h.m4 deleted file mode 100644 index 9f7d8c2e..00000000 --- a/sigc++/adaptors/macros/track_obj.h.m4 +++ /dev/null @@ -1,225 +0,0 @@ -dnl Copyright 2013, The libsigc++ Development Team -dnl -dnl This file is part of libsigc++. -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library. If not, see . -dnl -divert(-1) - -include(template.macros.m4) - -define([TRACK_OBJECT_OPERATOR],[dnl - /** Invokes the wrapped functor passing on the arguments.dnl -FOR(1, $1,[ - * @param _A_arg%1 Argument to be passed on to the functor.]) - * @return The return value of the functor invocation. - */ - template - typename deduce_result_type::type - operator()(LOOP(T_arg%1 _A_arg%1, $1)) - { - return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_arg%1, $1)); - } - - #ifndef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - template - typename deduce_result_type::type - sun_forte_workaround(LOOP(T_arg%1 _A_arg%1, $1)) - { - return this->functor_.SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(_A_arg%1, $1)); - } - #endif - -])dnl end TRACK_OBJECT_OPERATOR - -dnl track_obj_functor[2..CALL_SIZE]. $1 is assumed to be >= 2. -define([TRACK_OBJECT_FUNCTOR],[dnl -/** track_obj_functor$1 wraps a functor and stores $1 references to trackable objects. - * Use the convenience function track_obj() to create an instance of track_obj_functor$1. - * - * @tparam T_functor The type of functor to wrap.dnl -FOR(1,$1,[ - * @tparam T_obj%1 The type of a trackable object.]) - * - * @newin{2,4} - * - * @ingroup track_obj - */ -template -class track_obj_functor$1 : public track_obj_functor1 -{ -public: - /** Constructs a track_obj_functor$1 object that wraps the passed functor and - * stores references to the passed trackable objects. - * @param _A_func Functor.dnl -FOR(1,$1,[ - * @param _A_obj%1 Trackable object.]) - */ - track_obj_functor$1(const T_functor& _A_func, LOOP(const T_obj%1& _A_obj%1, $1)) - : track_obj_functor1(_A_func, _A_obj1)FOR(2,$1,[[, ]obj%1_(_A_obj%1)]) {} - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//protected: - // public, so that visit_each() can access it.dnl -FOR(2,$1,[ - const_limit_reference obj%1_;]) -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -}; // end class track_obj_functor$1 - -])dnl end TRACK_OBJECT_FUNCTOR - -define([TRACK_OBJECT_VISIT_EACH],[dnl -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::track_obj_functor$1 performs a functor - * on the functor and on the trackable object instances stored in the - * sigc::track_obj_functor$1 object. - * - * @newin{2,4} - * - * @ingroup track_obj - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const track_obj_functor$1& _A_target) - { - sigc::visit_each(_A_action, _A_target.functor_);dnl -FOR(1,$1,[ - sigc::visit_each(_A_action, _A_target.obj%1_);]) - } -}; - -])dnl end TRACK_OBJECT_VISIT_EACH - -define([TRACK_OBJECT],[dnl -/** Creates an adaptor of type sigc::track_obj_functor$1 which wraps a functor. - * @param _A_func Functor that shall be wrapped.dnl -FOR(1,$1,[ - * @param _A_obj%1 Trackable object.]) - * @return Adaptor that executes _A_func() on invocation. - * - * @newin{2,4} - * - * @ingroup track_obj - */ -template -inline track_obj_functor$1 -track_obj(const T_functor& _A_func, LOOP(const T_obj%1& _A_obj%1, $1)) -{ - return track_obj_functor$1 - (_A_func, LOOP(_A_obj%1, $1)); -} - -])dnl end TRACK_OBJECT - -divert(0)dnl -_FIREWALL([ADAPTORS_TRACK_OBJ]) -#include -#include - -namespace sigc { - -/** @defgroup track_obj track_obj() - * sigc::track_obj() tracks trackable objects, referenced from a functor. - * It can be useful when you assign a C++11 lambda expression or a std::function<> - * to a slot, or connect it to a signal, and the lambda expression or std::function<> - * contains references to sigc::trackable derived objects. - * - * The functor returned by sigc::track_obj() is formally an adaptor, but it does - * not alter the signature, return type or behaviour of the supplied functor. - * Up to CALL_SIZE objects can be tracked. operator()() can have up to CALL_SIZE arguments. - * - * @par Example: - * @code - * struct bar : public sigc::trackable {}; - * sigc::signal some_signal; - * void foo(bar&); - * { - * bar some_bar; - * some_signal.connect([[&some_bar]](){ foo(some_bar); }); - * // NOT disconnected automatically when some_bar goes out of scope - * some_signal.connect(sigc::track_obj([[&some_bar]](){ foo(some_bar); }, some_bar); - * // disconnected automatically when some_bar goes out of scope - * } - * @endcode - * - * @newin{2,4} - * - * @ingroup adaptors - */ - -/** track_obj_functor1 wraps a functor and stores a reference to a trackable object. - * Use the convenience function track_obj() to create an instance of track_obj_functor1. - * - * @tparam T_functor The type of functor to wrap. - * @tparam T_obj1 The type of a trackable object. - * - * @newin{2,4} - * - * @ingroup track_obj - */ -template -class track_obj_functor1 : public adapts -{ -public: - typedef typename adapts::adaptor_type adaptor_type; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS - template - struct deduce_result_type - { typedef typename adaptor_type::template deduce_result_type::type type; }; -#endif - typedef typename adaptor_type::result_type result_type; - - /** Constructs a track_obj_functor1 object that wraps the passed functor and - * stores a reference to the passed trackable object. - * @param _A_func Functor. - * @param _A_obj1 Trackable object. - */ - track_obj_functor1(const T_functor& _A_func, const T_obj1& _A_obj1) - : adapts(_A_func), obj1_(_A_obj1) {} - - /** Invokes the wrapped functor. - * @return The return value of the functor invocation. - */ - result_type operator()() - { return this->functor_(); } - -FOR(1,CALL_SIZE,[[TRACK_OBJECT_OPERATOR(%1)]])dnl - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//protected: - // public, so that visit_each() can access it. - const_limit_reference obj1_; -#endif /* DOXYGEN_SHOULD_SKIP_THIS */ - -}; // end class track_obj_functor1 - -FOR(2,CALL_SIZE,[[TRACK_OBJECT_FUNCTOR(%1)]])dnl - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -FOR(1,CALL_SIZE,[[TRACK_OBJECT_VISIT_EACH(%1)]])dnl -#endif // DOXYGEN_SHOULD_SKIP_THIS - -FOR(1,CALL_SIZE,[[TRACK_OBJECT(%1)]])dnl - -} /* namespace sigc */ diff --git a/sigc++/adaptors/retype.h b/sigc++/adaptors/retype.h new file mode 100644 index 00000000..14e2e3ea --- /dev/null +++ b/sigc++/adaptors/retype.h @@ -0,0 +1,154 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_RETYPE_H +#define SIGC_ADAPTORS_RETYPE_H + +#include +#include +#include +#include + +namespace sigc +{ + +/** @defgroup retype retype(), retype_return() + * sigc::retype() alters a sigc::pointer_functor, a sigc::mem_functor or + * a @ref sigc::slot "sigc::slot" + * in that it makes C-style casts to the functor's parameter types + * of all parameters passed through operator()(). + * + * Use this adaptor for inline conversion between numeric or other simple types. + * @par Example: + * @code + * void foo(int); + * sigc::retype(sigc::ptr_fun(&foo))(5.7F); // calls foo(5) + * @endcode + * + * The functor that sigc::retype() returns can be passed directly into + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" or + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()". + * + * @par Example: + * @code + * sigc::signal some_signal; + * void foo(int); + * some_signal.connect(sigc::retype(sigc::ptr_fun(&foo))); + * @endcode + * + * This adaptor builds an exception in that it only works on sigc::pointer_functor, + * sigc::mem_functor and @ref sigc::slot "sigc::slot" + * because it needs sophisticated information about + * the parameter types that cannot be deduced from arbitrary functor types. + * + * sigc::retype_return() alters the return type of an arbitrary functor. + * Like in sigc::retype() a C-style cast is performed. Usage sigc::retype_return() is + * not restricted to libsigc++ functor types but you need to + * specify the new return type as a template parameter. + * + * @par Example: + * @code + * float foo(); + * std::cout << sigc::retype_return(&foo)(); // converts foo's return value to an integer + * @endcode + * + * @ingroup adaptors + */ + +/** Adaptor that performs C-style casts on the parameters passed on to the functor. + * Use the convenience function sigc::retype() to create an instance of retype_functor. + * + * The following template arguments are used: + * - @e T_functor Type of the functor to wrap. + * - @e T_type Types of @e T_functor's arguments. + * + * @ingroup retype + */ +template +struct retype_functor : public adapts +{ + template + decltype(auto) operator()(T_arg... a) + { + return std::invoke(this->functor_, static_cast(a)...); + } + + /** Constructs a retype_functor object that performs C-style casts on the parameters passed on to + * the functor. + * @param functor Functor to invoke from operator()(). + */ + explicit retype_functor(type_trait_take_t functor) : adapts(functor) {} +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::retype_functor performs a functor on the + * functor stored in the sigc::retype_functor object. + * + * @ingroup retype + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const retype_functor& target) + { + sigc::visit_each(action, target.functor_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +// This one takes, for instance, a mem_functor or bound_mem_functor: +/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters + * passed on to the functor. + * + * @param functor Functor that should be wrapped. + * @return Adaptor that executes @e functor performing C-style casts on the paramters passed on. + * + * @ingroup retype + */ +template class T_functor, + typename T_func, + typename... T_arg> +inline decltype(auto) +retype(const T_functor& functor) +{ + return retype_functor, T_arg...>(functor); +} + +// This one takes, for instance, a pointer_functor or slot: +/** Creates an adaptor of type sigc::retype_functor which performs C-style casts on the parameters + * passed on to the functor. + * + * @param functor Functor that should be wrapped. + * @return Adaptor that executes @e functor performing C-style casts on the paramters passed on. + * + * @ingroup retype + */ +template class T_functor, + typename T_return, + typename... T_arg> +inline decltype(auto) +retype(const T_functor& functor) +{ + return retype_functor, T_arg...>(functor); +} + +} /* namespace sigc */ + +#endif /* SIGC_ADAPTORS_RETYPE_H */ diff --git a/sigc++/adaptors/retype_return.h b/sigc++/adaptors/retype_return.h new file mode 100644 index 00000000..bb7159db --- /dev/null +++ b/sigc++/adaptors/retype_return.h @@ -0,0 +1,129 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_RETYPE_RETURN_H +#define SIGC_ADAPTORS_RETYPE_RETURN_H +#include + +namespace sigc +{ + +/** Adaptor that performs a C-style cast on the return value of a functor. + * Use the convenience function sigc::retype_return() to create an instance of + * retype_return_functor. + * + * The following template arguments are used: + * - @e T_return Target type of the C-style cast. + * - @e T_functor Type of the functor to wrap. + * + * @ingroup retype + */ +template +struct retype_return_functor : public adapts +{ + template + inline T_return operator()(T_arg&&... a) + { + return T_return(std::invoke(this->functor_, std::forward(a)...)); + } + + retype_return_functor() = default; + + /** Constructs a retype_return_functor object that perform a C-style cast on the return value of + * the passed functor. + * @param functor Functor to invoke from operator()(). + */ + explicit retype_return_functor(type_trait_take_t functor) : adapts(functor) + { + } +}; + +/** Adaptor that performs a C-style cast on the return value of a functor. + * This template specialization is for a void return. It drops the return value of the functor it + * invokes. + * Use the convenience function sigc::hide_return() to create an instance of + * sigc::retype_return_functor. + * + * @ingroup retype + */ +/* The void specialization is needed because of explicit cast to T_return. + */ +template +struct retype_return_functor : public adapts +{ + template + inline void operator()(T_arg... a) + { + std::invoke(this->functor_, a...); + } + + retype_return_functor() = default; + retype_return_functor(type_trait_take_t functor) : adapts(functor) {} +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::retype_return_functor performs a functor on the + * functor stored in the sigc::retype_return_functor object. + * + * @ingroup retype + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const retype_return_functor& target) + { + sigc::visit_each(action, target.functor_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Creates an adaptor of type sigc::retype_return_functor which performs a C-style cast on the + * return value of the passed functor. + * The template argument @e T_return specifies the target type of the cast. + * + * @param functor Functor that should be wrapped. + * @return Adaptor that executes @e functor performing a C-style cast on the return value. + * + * @ingroup retype + */ +template +inline retype_return_functor +retype_return(const T_functor& functor) +{ + return retype_return_functor(functor); +} + +/** Creates an adaptor of type sigc::retype_return_functor which drops the return value of the + * passed functor. + * + * @param functor Functor that should be wrapped. + * @return Adaptor that executes @e functor dropping its return value. + * + * @ingroup hide + */ +template +inline retype_return_functor +hide_return(const T_functor& functor) +{ + return retype_return_functor(functor); +} + +} /* namespace sigc */ +#endif /* SIGC_ADAPTORS_RETYPE_RETURN_H */ diff --git a/sigc++/adaptors/track_obj.h b/sigc++/adaptors/track_obj.h new file mode 100644 index 00000000..60890cca --- /dev/null +++ b/sigc++/adaptors/track_obj.h @@ -0,0 +1,172 @@ +/* Copyright 2013 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_ADAPTORS_TRACK_OBJ_H +#define SIGC_ADAPTORS_TRACK_OBJ_H + +#include +#include +#include +#include +#include +#include +#include + +namespace sigc +{ + +/** @defgroup track_obj track_obj(), track_object() + * sigc::track_object() tracks trackable objects, referenced from a functor. + * It can be useful when you assign a C++11 lambda expression or a std::function<> + * to a slot, or connect it to a signal, and the lambda expression or std::function<> + * contains references to sigc::trackable derived objects. + * + * The functor returned by sigc::track_object() is formally an adaptor, but it does + * not alter the signature, return type or behaviour of the supplied functor. + * + * track_obj() is a deprecated alternative to track_object(). + * + * @par Example: + * @code + * struct bar : public sigc::trackable {}; + * sigc::signal some_signal; + * void foo(bar&); + * { + * bar some_bar; + * some_signal.connect([&some_bar](){ foo(some_bar); }); + * // NOT disconnected automatically when some_bar goes out of scope + * some_signal.connect(sigc::track_object([&some_bar](){ foo(some_bar); }, some_bar); + * // disconnected automatically when some_bar goes out of scope + * } + * @endcode + * + * @ingroup adaptors + */ + +/** %track_obj_functor wraps a functor and stores a reference to a trackable object. + * Use the convenience function track_object() to create an instance of %track_obj_functor. + * + * track_obj() is a deprecated alternative to track_object(). + * + * @tparam T_functor The type of functor to wrap. + * @tparam T_obj The types of the trackable objects. + * + * @newin{2,4} + * + * @ingroup track_obj + */ +template +class track_obj_functor : public adapts +{ +public: + /** Constructs a track_obj_functor object that wraps the passed functor and + * stores a reference to the passed trackable objects. + * @param func Functor. + * @param obj Trackable objects. + */ + explicit track_obj_functor(const T_functor& func, const T_obj&... obj) + : adapts(func), obj_(obj...) + { + } + + /** Invokes the wrapped functor passing on the arguments. + * @param arg Arguments to be passed on to the functor. + * @return The return value of the functor invocation. + */ + template + decltype(auto) operator()(T_arg&&... arg) + { + return std::invoke(this->functor_, std::forward(arg)...); + } + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + // protected: + // public, so that visit_each() can access it. + std::tuple...> obj_; +#endif /* DOXYGEN_SHOULD_SKIP_THIS */ + +}; // end class track_obj_functor + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::track_obj_functor performs a functor + * on the functor and on the trackable object instances stored in the + * sigc::track_obj_functor object. + * + * @newin{2,4} + * + * @ingroup track_obj + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const track_obj_functor& target) + { + sigc::visit_each(action, target.functor_); + + // Call sigc::visit_each(action, element) on each element in the + // target.obj_ tuple: + sigc::internal::tuple_for_each(target.obj_, action); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +#ifndef SIGCXX_DISABLE_DEPRECATED +/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor. + * @param func Functor that shall be wrapped. + * @param obj Trackable objects. + * @return Adaptor that executes func() on invocation. + * + * @newin{2,4} + * @deprecated Use sigc::track_object() instead. + * + * @ingroup track_obj + */ +template +inline decltype(auto) +track_obj(const T_functor& func, const T_obj&... obj) +{ + return track_obj_functor(func, obj...); +} +#endif // SIGCXX_DISABLE_DEPRECATED + +/** Creates an adaptor of type sigc::track_obj_functor which wraps a functor. + * @param func Functor that shall be wrapped. + * @param obj1 Trackable object, derived directly or indirectly from sigc::trackable. + * @param objs Zero or more trackable objects, derived directly or indirectly from sigc::trackable. + * @return Adaptor that executes func() on invocation. + * + * @newin{3,4} + * + * @ingroup track_obj + */ +template +inline decltype(auto) +track_object(const T_functor& func, const T_obj1& obj1, const T_objs&... objs) +{ + static_assert(std::min({ std::is_base_of::value, + std::is_base_of::value... }), + "Each trackable object must be derived from sigc::trackable."); + + return track_obj_functor(func, obj1, objs...); +} + +} /* namespace sigc */ + +#endif /* SIGC_ADAPTORS_TRACK_OBJ_H */ diff --git a/sigc++/adaptors/tuple_visitor_visit_each.h b/sigc++/adaptors/tuple_visitor_visit_each.h new file mode 100644 index 00000000..864b232e --- /dev/null +++ b/sigc++/adaptors/tuple_visitor_visit_each.h @@ -0,0 +1,45 @@ +/* Copyright 2015 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_TUPLE_VISITOR_VISIT_EACH_H +#define SIGC_TUPLE_VISITOR_VISIT_EACH_H + +#include +#include + +namespace sigc +{ + +namespace internal +{ + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +struct TupleVisitorVisitEach +{ + template + constexpr static void visit(const T_element& element, T_action&& action) + { + sigc::visit_each(std::forward(action), element); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} // namespace internal + +} // namespace sigc + +#endif /* SIGC_TUPLE_VISITOR_VISIT_EACH_H */ diff --git a/sigc++/bind.h b/sigc++/bind.h index 4741377c..989a4906 100644 --- a/sigc++/bind.h +++ b/sigc++/bind.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,13 +11,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_BIND_HPP_ -#define _SIGC_BIND_HPP_ +#ifndef SIGC_BIND_HPP +#define SIGC_BIND_HPP #include -#endif /* _SIGC_BIND_HPP_ */ +#endif /* SIGC_BIND_HPP */ diff --git a/sigc++/bind_return.h b/sigc++/bind_return.h index fa90c454..82bd3cbf 100644 --- a/sigc++/bind_return.h +++ b/sigc++/bind_return.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,14 +11,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_BIND_RETURN_HPP_ -#define _SIGC_BIND_RETURN_HPP_ +#ifndef SIGC_BIND_RETURN_HPP +#define SIGC_BIND_RETURN_HPP #include - -#endif /* _SIGC_BIND_RETURN_HPP_ */ +#endif /* SIGC_BIND_RETURN_HPP */ diff --git a/sigc++/connection.cc b/sigc++/connection.cc index 0d1d52eb..e7c7f2be 100644 --- a/sigc++/connection.cc +++ b/sigc++/connection.cc @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,98 +11,75 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ #include -namespace sigc { +namespace sigc +{ -connection::connection() noexcept -: slot_(nullptr) -{} +connection::connection() noexcept : slot_(nullptr) {} -connection::connection(const connection& c) -: slot_(c.slot_) -{ - //Let the connection forget about the signal handler when the handler object dies: - if (slot_) - slot_->add_destroy_notify_callback(this, ¬ify); -} +connection::connection(slot_base& slot) : slot_(&slot) {} -connection::connection(slot_base& sl) -: slot_(&sl) -{ - //Let the connection forget about the signal handler when the handler object dies: - slot_->add_destroy_notify_callback(this, ¬ify); -} +connection::connection(const connection& c) : slot_(c.slot_) {} -connection& connection::operator=(const connection& c) +connection& +connection::operator=(const connection& src) { - set_slot(c.slot_); + set_slot(src.slot_); return *this; } -connection::~connection() -{ - if (slot_) - slot_->remove_destroy_notify_callback(this); -} +connection::~connection() {} -bool connection::empty() const noexcept +bool +connection::empty() const noexcept { return (!slot_ || slot_->empty()); } -bool connection::connected() const noexcept +bool +connection::connected() const noexcept { return !empty(); } -bool connection::blocked() const noexcept +bool +connection::blocked() const noexcept { return (slot_ ? slot_->blocked() : false); } -bool connection::block(bool should_block) noexcept +bool +connection::block(bool should_block) noexcept { return (slot_ ? slot_->block(should_block) : false); } -bool connection::unblock() noexcept +bool +connection::unblock() noexcept { return (slot_ ? slot_->unblock() : false); } -void connection::disconnect() +void +connection::disconnect() { if (slot_) slot_->disconnect(); // This notifies slot_'s parent. -} +} -connection::operator bool() noexcept +connection::operator bool() const noexcept { return !empty(); } - -void connection::set_slot(slot_base* sl) -{ - if (slot_) - slot_->remove_destroy_notify_callback(this); - - slot_ = sl; - if (slot_) - slot_->add_destroy_notify_callback(this, ¬ify); -} - -void* connection::notify(void* data) +void +connection::set_slot(const sigc::internal::weak_raw_ptr& sl) { - auto self = reinterpret_cast(data); - self->slot_ = nullptr; - return nullptr; + slot_ = sl; } } /* namespace sigc */ diff --git a/sigc++/connection.h b/sigc++/connection.h index 81ad07a2..9d6f1ee7 100644 --- a/sigc++/connection.h +++ b/sigc++/connection.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,28 +11,38 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_CONNECTION_HPP_ -#define _SIGC_CONNECTION_HPP_ + +#ifndef SIGC_CONNECTION_HPP +#define SIGC_CONNECTION_HPP + #include -#include +#include +#include -namespace sigc { +namespace sigc +{ -/** Convinience class for safe disconnection. - * Iterators must not be used beyond the lifetime of the list - * they work on. A connection object can be created from a - * slot list iterator and may safely be used to disconnect - * the referred slot at any time (disconnect()). If the slot - * has already been destroyed, disconnect() does nothing. empty() or +/** Convenience class for safe disconnection. + * + * This may be used to disconnect the referred slot at any time (disconnect()). + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" and + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()" + * return a %sigc::connection. + * + * @code + * sigc::connection conn = sig.connect(sigc::mem_fun(a, &A::foo)); + * @endcode + * + * If the slot has already been destroyed, disconnect() does nothing. empty() or * operator bool() can be used to test whether the connection is * still active. The connection can be blocked (block(), unblock()). * - * This is possible because the connection object gets notified - * when the referred slot dies (notify()). + * sigc::connection doesnʼt disconnect the slot automatically upon destruction. + * You do not need to keep the sigc::connection object to retain the connection + * of the slot to the signal. See also @ref sigc::scoped_connection, which does + * disconnect automatically when the connection object is destroyed or replaced. * * @ingroup signal */ @@ -47,30 +56,15 @@ struct SIGC_API connection */ connection(const connection& c); - /** Constructs a connection object from a slot list iterator. - * @param it The slot list iterator to take the slot from. - */ - template - connection(const slot_iterator& it) : slot_(&(*it)) - { if (slot_) slot_->add_destroy_notify_callback(this, ¬ify); } - /** Constructs a connection object from a slot object. - * This is only useful if you create your own slot list. - * @param sl The slot to operate on. + * @param slot The slot to operate on. */ - explicit connection(slot_base& sl); + explicit connection(slot_base& slot); /** Overrides this connection object copying another one. - * @param c The connection object to make a copy from. - */ - connection& operator=(const connection& c); - - /** Overrides this connection object with another slot list iterator. - * @param it The new slot list iterator to take the slot from. + * @param src The connection object to make a copy from. */ - template - connection& operator=(const slot_iterator& it) - { set_slot(&(*it)); return *this; } + connection& operator=(const connection& src); ~connection(); @@ -104,27 +98,20 @@ struct SIGC_API connection /// Disconnects the referred slot. void disconnect(); - //TODO: When we can break API and ABI, make operator bool() const /** Returns whether the connection is still active. * @return @p true if the connection is still active. */ - explicit operator bool() noexcept; - - /** Callback that is executed when the referred slot is destroyed. - * @param data The connection object notified (@p this). - */ - static void* notify(void* data); + explicit operator bool() const noexcept; private: - void set_slot(slot_base* sl); + void set_slot(const sigc::internal::weak_raw_ptr& sl); - /* Referred slot. Set to zero from notify(). - * A value of zero indicates an "empty" connection. + /* Referred slot. Set to nullptr when the referred slot is deleted. + * A value of nullptr indicates an "empty" connection. */ - slot_base* slot_; + sigc::internal::weak_raw_ptr slot_; }; } /* namespace sigc */ - -#endif /* _SIGC_TRACKABLE_HPP_ */ +#endif /* SIGC_CONNECTION_HPP */ diff --git a/sigc++/filelist.am b/sigc++/filelist.am index 9663ea86..ea9155fb 100644 --- a/sigc++/filelist.am +++ b/sigc++/filelist.am @@ -15,56 +15,53 @@ ## You should have received a copy of the GNU Lesser General Public License ## along with this library. If not, see . -# Base (./) -base_m4 = template.macros.m4 signal.h.m4 limit_reference.h.m4 -base_built_cc = -base_built_h = signal.h limit_reference.h - -# Functors (functors/) -functors_m4 = functor_trait.h.m4 slot.h.m4 ptr_fun.h.m4 mem_fun.h.m4 -functors_built_cc = -functors_built_h = functor_trait.h slot.h ptr_fun.h mem_fun.h - -# Adaptors (adaptors/) -adaptors_m4 = deduce_result_type.h.m4 adaptor_trait.h.m4 bind.h.m4 bind_return.h.m4 \ - retype_return.h.m4 hide.h.m4 retype.h.m4 compose.h.m4 exception_catch.h.m4 \ - track_obj.h.m4 -adaptors_built_cc = -adaptors_built_h = deduce_result_type.h adaptor_trait.h bind.h bind_return.h \ - retype_return.h hide.h retype.h compose.h exception_catch.h \ - track_obj.h - -# Lambda (adaptors/lambda) -lambda_m4 = base.h.m4 select.h.m4 lambda.cc.m4 -lambda_built_cc = lambda.cc -lambda_built_h = base.h select.h - -# Combine all the above parts with right directories prefixed -sigc_m4 = $(base_m4:%=macros/%) \ - $(functors_m4:%=functors/macros/%) \ - $(adaptors_m4:%=adaptors/macros/%) \ - $(lambda_m4:%=adaptors/lambda/macros/%) -sigc_built_cc = $(base_built_cc) \ - $(functors_built_cc:%=functors/%) \ - $(adaptors_built_cc:%=adaptors/%) \ - $(lambda_built_cc:%=adaptors/lambda/%) -sigc_built_h = $(base_built_h) \ - $(functors_built_h:%=functors/%) \ - $(adaptors_built_h:%=adaptors/%) \ - $(lambda_built_h:%=adaptors/lambda/%) sigc_public_h = \ bind.h \ bind_return.h \ connection.h \ + limit_reference.h \ + member_method_trait.h \ reference_wrapper.h \ retype_return.h \ + scoped_connection.h \ + signal.h \ signal_base.h \ + signal_connect.h \ slot.h \ trackable.h \ + tuple-utils/tuple_cdr.h \ + tuple-utils/tuple_end.h \ + tuple-utils/tuple_for_each.h \ + tuple-utils/tuple_start.h \ + tuple-utils/tuple_transform_each.h \ type_traits.h \ visit_each.h \ + weak_raw_ptr.h \ + adaptors/adapts.h \ + adaptors/adaptor_base.h \ adaptors/adaptors.h \ + adaptors/adaptor_trait.h \ + adaptors/bind.h \ + adaptors/bind_return.h \ adaptors/bound_argument.h \ + adaptors/compose.h \ + adaptors/exception_catch.h \ + adaptors/hide.h \ + adaptors/retype.h \ + adaptors/track_obj.h \ + adaptors/retype_return.h \ + adaptors/tuple_visitor_visit_each.h \ + functors/functor_trait.h \ functors/functors.h \ + functors/mem_fun.h \ + functors/ptr_fun.h \ + functors/slot.h \ functors/slot_base.h + +sigc_sources_cc = \ + scoped_connection.cc \ + signal_base.cc \ + trackable.cc \ + connection.cc \ + functors/slot_base.cc diff --git a/sigc++/functors/functor_trait.h b/sigc++/functors/functor_trait.h new file mode 100644 index 00000000..e83b36b9 --- /dev/null +++ b/sigc++/functors/functor_trait.h @@ -0,0 +1,89 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_FUNCTORS_FUNCTOR_TRAIT_H +#define SIGC_FUNCTORS_FUNCTOR_TRAIT_H + +#include +#include +#include +#include + +namespace sigc +{ + +/** @defgroup sigcfunctors Functors + * Functors are copyable types that define operator()(). + * + * Types that define operator()() overloads with different return types are referred to + * as multi-type functors. Multi-type functors are only partially supported in libsigc++. + * + * Closures are functors that store all information needed to invoke a callback from operator()(). + * + * Adaptors are functors that alter the signature of a functor's operator()(). + * + * libsigc++ defines numerous functors, closures and adaptors. + * Since libsigc++ is a callback library, most functors are also closures. + * The documentation doesn't distinguish between functors and closures. + * + * The basic functor types libsigc++ provides are created with ptr_fun() and mem_fun() + * and can be converted into slots implicitly. + * The set of adaptors that ships with libsigc++ is documented in the @ref adaptors module. + * + */ + +/** Trait that specifies the appropriate functor type of any callable type. + * Template specializations for function pointers and for class methods are provided. + * + * @tparam T_functor Functor type. + * + * @ingroup sigcfunctors + */ +template +struct functor_trait +{ + using functor_type = T_functor; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// detect the functor version of non-functor types. + +// functor ptr fun: + +template +struct functor_trait +{ + using functor_type = pointer_functor; +}; + +// functor mem fun: + +template +struct functor_trait +{ + using functor_type = mem_functor; +}; + +template +struct functor_trait +{ + using functor_type = mem_functor; +}; + +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} /* namespace sigc */ +#endif /* SIGC_FUNCTORS_FUNCTOR_TRAIT_H */ diff --git a/sigc++/functors/functors.h b/sigc++/functors/functors.h index 3a9619c2..6f08b0a4 100644 --- a/sigc++/functors/functors.h +++ b/sigc++/functors/functors.h @@ -1,6 +1,4 @@ -// -*- c++ -*- -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -13,15 +11,13 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_FUNCTOR_HPP_ -#define _SIGC_FUNCTOR_HPP_ +#ifndef SIGC_FUNCTOR_HPP +#define SIGC_FUNCTOR_HPP #include #include #include -#endif /* _SIGC_FUNCTOR_HPP_ */ +#endif /* SIGC_FUNCTOR_HPP */ diff --git a/sigc++/functors/macros/functor_trait.h.m4 b/sigc++/functors/macros/functor_trait.h.m4 deleted file mode 100644 index 59a9b9b9..00000000 --- a/sigc++/functors/macros/functor_trait.h.m4 +++ /dev/null @@ -1,277 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) -include(template.macros.m4) - -define([FUNCTOR_PTR_FUN],[dnl -template class pointer_functor$1; -template -struct functor_trait -{ - typedef T_return result_type; - typedef pointer_functor$1 functor_type; -}; - -]) -define([FUNCTOR_MEM_FUN],[dnl -template class mem_functor$1; -template class const_mem_functor$1; -template -struct functor_trait -{ - typedef T_return result_type; - typedef mem_functor$1 functor_type; -}; -template -struct functor_trait -{ - typedef T_return result_type; - typedef const_mem_functor$1 functor_type; -}; - -]) - -divert(0)dnl -_FIREWALL([FUNCTORS_FUNCTOR_TRAIT]) -#include -#include - -namespace sigc { - -//TODO: When we can break ABI, replace nil by something else, such as sigc_nil. -// nil is a keyword in Objective C++. When gcc is used for compiling Objective C++ -// programs, nil is defined as a preprocessor macro. -// https://bugzilla.gnome.org/show_bug.cgi?id=695235 -#if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO) - #define SIGC_NIL_HAS_BEEN_PUSHED 1 - #pragma push_macro("nil") - #undef nil -#endif - -/** nil struct type. - * The nil struct type is used as default template argument in the - * unnumbered sigc::signal and sigc::slot templates. - * - * @ingroup signal - * @ingroup slot - */ -#ifndef DOXYGEN_SHOULD_SKIP_THIS -struct nil; -#else -struct nil {}; -#endif - -#ifdef SIGC_NIL_HAS_BEEN_PUSHED - #undef SIGC_NIL_HAS_BEEN_PUSHED - #pragma pop_macro("nil") -#endif - -/** @defgroup sigcfunctors Functors - * Functors are copyable types that define operator()(). - * - * Types that define operator()() overloads with different return types are referred to - * as multi-type functors. Multi-type functors are only partially supported in libsigc++. - * - * Closures are functors that store all information needed to invoke a callback from operator()(). - * - * Adaptors are functors that alter the signature of a functor's operator()(). - * - * libsigc++ defines numerous functors, closures and adaptors. - * Since libsigc++ is a callback library, most functors are also closures. - * The documentation doesn't distinguish between functors and closures. - * - * The basic functor types libsigc++ provides are created with ptr_fun() and mem_fun() - * and can be converted into slots implicitly. - * The set of adaptors that ships with libsigc++ is documented in the @ref adaptors module. - * - * If you want to mix user-defined and third party functors with libsigc++, - * and you want them to be implicitly convertible into slots, libsigc++ must know - * the result type of your functors. There are different ways to achieve that. - * - * - Derive your functors from sigc::functor_base and place - * typedef T_return result_type; in the class definition. - * - Use the macro SIGC_FUNCTOR_TRAIT(T_functor,T_return) in namespace sigc. - * Multi-type functors are only partly supported. - * - For functors not derived from sigc::functor_base, and not specified with - * SIGC_FUNCTOR_TRAIT(), libsigc++ tries to deduce the result type with the - * C++11 decltype() specifier. That attempt usually succeeds if the functor - * has a single operator()(), but it fails if operator()() is overloaded. - * - Use the macro #SIGC_FUNCTORS_HAVE_RESULT_TYPE, if you want libsigc++ to assume - * that result_type is defined in all user-defined or third party functors, - * whose result type can't be deduced in any other way. - * - * If all these ways to deduce the result type fail, void is assumed. - * - * With libsigc++ versions before 2.6, the macro - * #SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE activated the test with - * decltype(). That macro is now unneccesary and deprecated. - */ - -/** A hint to the compiler. - * All functors which define @p result_type should publically inherit from this hint. - * - * @ingroup sigcfunctors - */ -struct functor_base {}; - -/** Helper class, to determine if decltype() can deduce the result type of a functor. - * - * @ingroup sigcfunctors - */ -template -class can_deduce_result_type_with_decltype -{ -private: - struct biggerthanint - { - int memory1; - int memory2; - int memory3; - int memory4; - }; - - static biggerthanint checksize(...); - - // If decltype(&X_functor::operator()) can't be evaluated, this checksize() overload - // is ignored because of the SFINAE rule (Substitution Failure Is Not An Error). - template - static int checksize(X_functor* obj, decltype(&X_functor::operator()) p = nullptr); - -public: - static const bool value -#ifndef DOXYGEN_SHOULD_SKIP_THIS - = sizeof(checksize(static_cast(nullptr))) == sizeof(int) -#endif - ; -}; - - -/** Trait that specifies the return type of any type. - * Template specializations for functors derived from sigc::functor_base, - * for other functors whose result type can be deduced with decltype(), - * for function pointers and for class methods are provided. - * - * @tparam T_functor Functor type. - * @tparam I_derives_functor_base Whether @p T_functor inherits from sigc::functor_base. - * @tparam I_can_use_decltype Whether the result type of @p T_functor can be deduced - * with decltype(). - * - * @ingroup sigcfunctors - */ -template ::value, - bool I_can_use_decltype = can_deduce_result_type_with_decltype::value> -struct functor_trait -{ - typedef void result_type; - typedef T_functor functor_type; -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -template -struct functor_trait -{ - typedef typename T_functor::result_type result_type; - typedef T_functor functor_type; -}; - -template -struct functor_trait -{ - typedef typename functor_trait::result_type result_type; - typedef T_functor functor_type; -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -/** Helper macro, if you want to mix user-defined and third party functors with libsigc++. - * - * If you want to mix functors not derived from sigc::functor_base with libsigc++, and - * these functors define @p result_type, use this macro inside namespace sigc like so: - * @code - * namespace sigc { SIGC_FUNCTORS_HAVE_RESULT_TYPE } - * @endcode - * - * @ingroup sigcfunctors - */ -#define SIGC_FUNCTORS_HAVE_RESULT_TYPE \ -template \ -struct functor_trait \ -{ \ - typedef typename T_functor::result_type result_type; \ - typedef T_functor functor_type; \ -}; - -/** Helper macro, if you want to mix user-defined and third party functors with libsigc++. - * - * If you want to mix functors not derived from sigc::functor_base with libsigc++, and - * these functors don't define @p result_type, use this macro inside namespace sigc - * to expose the return type of the functors like so: - * @code - * namespace sigc { - * SIGC_FUNCTOR_TRAIT(first_functor_type, return_type_of_first_functor_type) - * SIGC_FUNCTOR_TRAIT(second_functor_type, return_type_of_second_functor_type) - * ... - * } - * @endcode - * - * @ingroup sigcfunctors - */ -#define SIGC_FUNCTOR_TRAIT(T_functor,T_return) \ -template <> \ -struct functor_trait \ -{ \ - typedef T_return result_type; \ - typedef T_functor functor_type; \ -}; \ -template <> \ -struct functor_trait \ -{ \ - typedef T_return result_type; \ - typedef T_functor functor_type; \ -}; - -#ifndef SIGCXX_DISABLE_DEPRECATED -/** Helper macro, if you want to mix user-defined and third party functors with libsigc++. - * - * If you want to mix functors not derived from sigc::functor_base with libsigc++, - * and your compiler can deduce the result type of the functor with the C++11 - * keyword decltype, use this macro inside namespace sigc like so: - * @code - * namespace sigc { - * SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE - * } - * @endcode - * - * Functors with overloaded operator()() are not supported. - * - * @newin{2,2,11} - * - * @deprecated This macro does nothing. The test it activated in libsigc++ - * versions before 2.6, is now unconditionally activated. - * - * @ingroup sigcfunctors - */ -#define SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE // Empty -#endif // SIGCXX_DISABLE_DEPRECATED - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -// detect the return type and the functor version of non-functor types. -FOR(0,CALL_SIZE,[[FUNCTOR_PTR_FUN(%1)]]) -FOR(0,CALL_SIZE,[[FUNCTOR_MEM_FUN(%1)]]) -#endif // DOXYGEN_SHOULD_SKIP_THIS - -} /* namespace sigc */ diff --git a/sigc++/functors/macros/mem_fun.h.m4 b/sigc++/functors/macros/mem_fun.h.m4 deleted file mode 100644 index 90d1889d..00000000 --- a/sigc++/functors/macros/mem_fun.h.m4 +++ /dev/null @@ -1,281 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([MEMBER_FUNCTOR],[dnl -/** [$2]mem_functor$1 wraps $4 methods with $1 argument(s). - * Use the convenience function mem_fun() to create an instance of [$2]mem_functor$1. - * - * The following template arguments are used:dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of operator()().]) - * - @e T_return The return type of operator()(). - * - @e T_obj The object type. - * - * @ingroup mem_fun - */ -template -class [$2]mem_functor$1 : public functor_base -{ -public: - typedef T_return (T_obj::*function_type)(LOOP(T_arg%1, $1)) $4; - typedef T_return result_type; - - /// Constructs an invalid functor. - [$2]mem_functor$1() : func_ptr_(nullptr) {} - - /** Constructs a [$2]mem_functor$1 object that wraps the passed method. - * @param _A_func Pointer to method will be invoked from operator()(). - */ - explicit [$2]mem_functor$1(function_type _A_func) : func_ptr_(_A_func) {} - - /** Execute the wrapped method operating on the passed instance. - * @param _A_obj Pointer to instance the method should operate on.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the method.]) - * @return The return value of the method invocation. - */ - T_return operator()(LIST($3 T_obj* _A_obj, LOOP(type_trait_take_t _A_a%1, $1))) const - { return (_A_obj->*(this->func_ptr_))(LOOP(_A_a%1, $1)); } - - /** Execute the wrapped method operating on the passed instance. - * @param _A_obj Reference to instance the method should operate on.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the method.]) - * @return The return value of the method invocation. - */ - T_return operator()(LIST($3 T_obj& _A_obj, LOOP(type_trait_take_t _A_a%1, $1))) const - { return (_A_obj.*func_ptr_)(LOOP(_A_a%1, $1)); } - -protected: - function_type func_ptr_; -}; - -]) -define([BOUND_MEMBER_FUNCTOR],[dnl - -/** bound_[$2]mem_functor$1 encapsulates a $4 method with $1 arguments and an object instance. - * Use the convenience function mem_fun() to create an instance of bound_[$2]mem_functor$1. - * - * The following template arguments are used:dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of operator()().]) - * - @e T_return The return type of operator()(). - * - @e T_obj The object type. - * - * @ingroup mem_fun - */ -template -class bound_[$2]mem_functor$1 - : public [$2]mem_functor$1 -{ - typedef [$2]mem_functor$1 base_type_; -public: - typedef typename base_type_::function_type function_type; - - /** Constructs a bound_[$2]mem_functor$1 object that wraps the passed method. - * @param _A_obj Pointer to instance the method will operate on. - * @param _A_func Pointer to method will be invoked from operator()(). - */ - bound_[$2]mem_functor$1($3 T_obj* _A_obj, function_type _A_func) - : base_type_(_A_func), - obj_(*_A_obj) - {} - - /** Constructs a bound_[$2]mem_functor$1 object that wraps the passed method. - * @param _A_obj Reference to instance the method will operate on. - * @param _A_func Pointer to method will be invoked from operator()(). - */ - bound_[$2]mem_functor$1($3 T_obj& _A_obj, function_type _A_func) - : base_type_(_A_func), - obj_(_A_obj) - {} - - /** Execute the wrapped method operating on the stored instance.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the method.]) - * @return The return value of the method invocation. - */ - T_return operator()(LOOP(type_trait_take_t _A_a%1, $1)) const - { return (obj_.invoke().*(this->func_ptr_))(LOOP(_A_a%1, $1)); } - -//protected: - // Reference to stored object instance. - // This is the handler object, such as TheObject in void TheObject::signal_handler(). - [$2]limit_reference obj_; -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overload for sigc::bound_[$2]mem_functor performs a functor - * on the object instance stored in the sigc::bound_[$2]mem_functor object. - * - * @ingroup mem_fun - */ -template -struct visitor > -{ - template - static void do_visit_each(const T_action& _A_action, - const bound_[$2]mem_functor$1& _A_target) - { - sigc::visit_each(_A_action, _A_target.obj_); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS -]) - -define([MEM_FUN],[dnl -/** Creates a functor of type sigc::[$3]mem_functor$1 which wraps a $5 method. - * @param _A_func Pointer to method that should be wrapped. - * @return Functor that executes _A_func on invokation. - * - * @ingroup mem_fun - */ -template -inline [$3]mem_functor$1 -mem_fun[]ifelse($2,, $1)(T_return (T_obj::*_A_func)(LOOP(T_arg%1,$1)) $5) -{ return [$3]mem_functor$1(_A_func); } - -]) -define([BOUND_MEM_FUN],[dnl -/** Creates a functor of type sigc::bound_[$3]mem_functor$1 which encapsulates a method and an object instance. - * @param _A_obj Pointer to object instance the functor should operate on. - * @param _A_func Pointer to method that should be wrapped. - * @return Functor that executes @e _A_func on invokation. - * - * @ingroup mem_fun - */ -template -inline bound_[$3]mem_functor$1 -mem_fun[]ifelse($2,, $1)(/*$4*/ T_obj* _A_obj, T_return (T_obj2::*_A_func)(LOOP(T_arg%1,$1)) $5) -{ return bound_[$3]mem_functor$1(_A_obj, _A_func); } - -/** Creates a functor of type sigc::bound_[$3]mem_functor$1 which encapsulates a method and an object instance. - * @param _A_obj Reference to object instance the functor should operate on. - * @param _A_func Pointer to method that should be wrapped. - * @return Functor that executes @e _A_func on invokation. - * - * @ingroup mem_fun - */ -template -inline bound_[$3]mem_functor$1 -mem_fun[]ifelse($2,, $1)(/*$4*/ T_obj& _A_obj, T_return (T_obj2::*_A_func)(LOOP(T_arg%1,$1)) $5) -{ return bound_[$3]mem_functor$1(_A_obj, _A_func); } - -]) - -divert(0) - -// implementation notes: -// - we do not use bind here, because it would introduce -// an extra copy and complicate the header include order if bind is -// to have automatic conversion for member pointers. -_FIREWALL([FUNCTORS_MEM_FUN]) -#include -#include -#include - -namespace sigc { - -/** @defgroup mem_fun mem_fun() - * mem_fun() is used to convert a pointer to a method to a functor. - * - * Optionally, a reference or pointer to an object can be bound to the functor. - * - * @note Only if the object type inherits from sigc::trackable, and the - * functor returned from mem_fun() is assigned to a sigc::slot, is the functor - * automatically cleared when the object goes out of scope! - * - * If the member function pointer is to an overloaded type, you must specify - * the types using template arguments starting with the first argument. - * It is not necessary to supply the return type. - * - * @par Example: - * @code - * struct foo : public sigc::trackable - * { - * void bar(int) {} - * }; - * foo my_foo; - * sigc::slot sl = sigc::mem_fun(my_foo, &foo::bar); - * // Note: f is not a slot. It will not be invalidated when my_foo is deleted. - * auto f = sigc::mem_fun(my_foo, &foo::bar); // Usually not what you want. - * @endcode - * - * For const methods mem_fun() takes a const reference or pointer to an object. - * - * @par Example: - * @code - * struct foo : public sigc::trackable - * { - * void bar(int) const {} - * }; - * const foo my_foo; - * sigc::slot sl = sigc::mem_fun(my_foo, &foo::bar); - * @endcode - * - * Use mem_fun#() if there is an ambiguity as to the number of arguments. - * - * @par Example: - * @code - * struct foo : public sigc::trackable - * { - * void bar(int) {} - * void bar(float) {} - * void bar(int, int) {} - * }; - * foo my_foo; - * sigc::slot sl = sigc::mem_fun1(my_foo, &foo::bar); - * @endcode - * - * @ingroup sigcfunctors - */ - -FOR(0,CALL_SIZE,[[MEMBER_FUNCTOR(%1,[],[],[])]])dnl -FOR(0,CALL_SIZE,[[MEMBER_FUNCTOR(%1,[const_],[const],[const])]])dnl -FOR(0,CALL_SIZE,[[MEMBER_FUNCTOR(%1,[volatile_],[],[volatile])]])dnl -FOR(0,CALL_SIZE,[[MEMBER_FUNCTOR(%1,[const_volatile_],[const],[const volatile])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEMBER_FUNCTOR(%1,[],[],[])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEMBER_FUNCTOR(%1,[const_],[const],[const])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEMBER_FUNCTOR(%1,[volatile_],[],[volatile])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEMBER_FUNCTOR(%1,[const_volatile_],[const],[const volatile])]])dnl - -// numbered -FOR(0,CALL_SIZE,[[MEM_FUN(%1,,[],[],[])]])dnl -FOR(0,CALL_SIZE,[[MEM_FUN(%1,,[const_],[const],[const])]])dnl -FOR(0,CALL_SIZE,[[MEM_FUN(%1,,[volatile_],[],[volatile])]])dnl -FOR(0,CALL_SIZE,[[MEM_FUN(%1,,[const_volatile_],[const],[const volatile])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,,[],[],[])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,,[const_],[const],[const])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,,[volatile_],[],[volatile])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,,[const_volatile_],[const],[const volatile])]])dnl - -// unnumbered -FOR(0,CALL_SIZE,[[MEM_FUN(%1,1,[],[],[])]])dnl -FOR(0,CALL_SIZE,[[MEM_FUN(%1,1,[const_],[const],[const])]])dnl -FOR(0,CALL_SIZE,[[MEM_FUN(%1,1,[volatile_],[],[volatile])]])dnl -FOR(0,CALL_SIZE,[[MEM_FUN(%1,1,[const_volatile_],[const],[const volatile])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,1,[],[],[])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,1,[const_],[const],[const])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,1,[volatile_],[],[volatile])]])dnl -FOR(0,CALL_SIZE,[[BOUND_MEM_FUN(%1,1,[const_volatile_],[const],[const volatile])]])dnl - -} /* namespace sigc */ diff --git a/sigc++/functors/macros/ptr_fun.h.m4 b/sigc++/functors/macros/ptr_fun.h.m4 deleted file mode 100644 index 355b01cb..00000000 --- a/sigc++/functors/macros/ptr_fun.h.m4 +++ /dev/null @@ -1,126 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([POINTER_FUNCTOR],[dnl -/** pointer_functor$1 wraps existing non-member functions with $1 argument(s). - * Use the convenience function ptr_fun() to create an instance of pointer_functor$1. - * - * The following template arguments are used:dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of operator()().]) - * - @e T_return The return type of operator()(). - * - * @ingroup ptr_fun - */ -template -class pointer_functor$1 : public functor_base -{ - typedef T_return (*function_type)(LOOP(T_arg%1, $1)); -protected: - function_type func_ptr_; -public: - typedef T_return result_type; - - /// Constructs an invalid functor. - pointer_functor$1() {} - - /** Constructs a pointer_functor$1 object that wraps an existing function. - * @param _A_func Pointer to function that will be invoked from operator()(). - */ - explicit pointer_functor$1(function_type _A_func): func_ptr_(_A_func) {} - - /** Execute the wrapped function.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the function.]) - * @return The return value of the function invocation. - */ - T_return operator()(LOOP(type_trait_take_t _A_a%1, $1)) const - { return func_ptr_(LOOP(_A_a%1, $1)); } -}; - -]) - -define([PTR_FUN],[dnl -/** Creates a functor of type sigc::pointer_functor$1 which wraps an existing non-member function. - * @param _A_func Pointer to function that should be wrapped. - * @return Functor that executes @e _A_func on invokation. - * - * @ingroup ptr_fun - */ -template -inline pointer_functor$1 -ptr_fun[]ifelse($2,, $1)(T_return (*_A_func)(LOOP(T_arg%1,$1))) -{ return pointer_functor$1(_A_func); } - -]) - -divert(0) -_FIREWALL([FUNCTORS_PTR_FUN]) -#include -#include - -namespace sigc { - -/** @defgroup ptr_fun ptr_fun() - * ptr_fun() is used to convert a pointer to a function to a functor. - * If the function pointer is to an overloaded type, you must specify - * the types using template arguments starting with the first argument. - * It is not necessary to supply the return type. - * - * @par Example: - * @code - * void foo(int) {} - * sigc::slot sl = sigc::ptr_fun(&foo); - * @endcode - * - * Use ptr_fun#() if there is an ambiguity as to the number of arguments. - * - * @par Example: - * @code - * void foo(int) {} // choose this one - * void foo(float) {} - * void foo(int, int) {} - * sigc::slot sl = sigc::ptr_fun1(&foo); - * @endcode - * - * ptr_fun() can also be used to convert a pointer to a static member - * function to a functor, like so: - * - * @par Example: - * @code - * struct foo - * { - * static void bar(int) {} - * }; - * sigc::slot sl = sigc::ptr_fun(&foo::bar); - * @endcode - * - * @ingroup sigcfunctors - */ - -FOR(0,CALL_SIZE,[[POINTER_FUNCTOR(%1)]])dnl - -// numbered ptr_fun -FOR(0,CALL_SIZE,[[PTR_FUN(%1)]])dnl - -// unnumbered ptr_fun -FOR(0,CALL_SIZE,[[PTR_FUN(%1,1)]])dnl - -} /* namespace sigc */ diff --git a/sigc++/functors/macros/slot.h.m4 b/sigc++/functors/macros/slot.h.m4 deleted file mode 100644 index 5c6436ca..00000000 --- a/sigc++/functors/macros/slot.h.m4 +++ /dev/null @@ -1,455 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([SLOT_N],[dnl -/** Converts an arbitrary functor to a unified type which is opaque. - * sigc::slot itself is a functor or to be more precise a closure. It contains - * a single, arbitrary functor (or closure) that is executed in operator()(). - * - * The template arguments determine the function signature of operator()(): - * - @e T_return The return type of operator()().dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of operator()(). The default @p nil means no argument.]) - * - * To use simply assign the desired functor to the slot. If the functor - * is not compatible with the parameter list defined with the template - * arguments compiler errors are triggered. When called the slot - * will invoke the functor with minimal copies. - * block() and unblock() can be used to block the functor's invocation - * from operator()() temporarily. - * - * You should use the more convenient unnumbered sigc::slot template. - * - * @ingroup slot - */ -template -class slot$1 - : public slot_base -{ -public: - typedef T_return result_type; -FOR(1, $1,[ typedef _R_(T_arg%1) arg%1_type_; -]) - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -private: - typedef internal::slot_rep rep_type; -public: - typedef T_return (*call_type)(LIST(rep_type*, LOOP(arg%1_type_, $1))); -#endif - - /** Invoke the contained functor unless slot is in blocking state.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the functor.]) - * @return The return value of the functor invocation. - */ - inline T_return operator()(LOOP(arg%1_type_ _A_a%1, $1)) const - { - if (!empty() && !blocked()) - return (reinterpret_cast(slot_base::rep_->call_))(LIST(slot_base::rep_, LOOP(_A_a%1, $1))); - return T_return(); - } - - inline slot$1() {} - - /** Constructs a slot from an arbitrary functor. - * @param _A_func The desired functor the new slot should be assigned to. - */ - template - slot$1(const T_functor& _A_func) - : slot_base(new internal::typed_slot_rep(_A_func)) - { - //The slot_base:: is necessary to stop the HP-UX aCC compiler from being confused. murrayc. - slot_base::rep_->call_ = internal::slot_call$1::address(); - } - - /** Constructs a slot, copying an existing one. - * @param src The existing slot to copy. - */ - slot$1(const slot$1& src) - : slot_base(src) - {} - - /** Constructs a slot, moving an existing one. - * If @p src is connected to a parent (e.g. a signal), it is copied, not moved. - * @param src The existing slot to move or copy. - */ - slot$1(slot$1&& src) - : slot_base(std::move(src)) - {} - - /** Overrides this slot, making a copy from another slot. - * @param src The slot from which to make a copy. - * @return @p this. - */ - slot$1& operator=(const slot$1& src) - { - slot_base::operator=(src); - return *this; - } - - /** Overrides this slot, making a move from another slot. - * If @p src is connected to a parent (e.g. a signal), it is copied, not moved. - * @param src The slot from which to move or copy. - * @return @p this. - */ - slot$1& operator=(slot$1&& src) - { - slot_base::operator=(std::move(src)); - return *this; - } -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * The function overloads for sigc::slot$1 are similar to the function - * overloads for sigc::slot. See the description of those overloads. - * - * @ingroup slot - */ -template -struct visitor> -{ - static void do_visit_each(const internal::limit_derived_target& _A_action, - const slot$1& _A_target) - { - if (_A_target.rep_ && _A_target.rep_->parent_ == nullptr) - _A_target.rep_->set_parent(_A_action.action_.rep_, &internal::slot_rep::notify); - } - - static void do_visit_each(const internal::limit_derived_target& _A_action, - const slot$1& _A_target) - { - if (_A_target.rep_ && _A_target.rep_->parent_ == _A_action.action_.rep_) - _A_target.rep_->set_parent(nullptr, nullptr); - } - - template - static void do_visit_each(const T_action& _A_action, - const slot$1& _A_target) - { - _A_action(_A_target); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS - -]) -define([SLOT],[dnl -ifelse($1, $2,[dnl -// Because slot is opaque, visit_each() will not visit its internal members. -// Those members are not reachable by visit_each() after the slot has been -// constructed. But when a slot contains another slot, the outer slot will become -// the parent of the inner slot, with similar results. See the description of -// slot's specialization of the visitor struct. -/** Convenience wrapper for the numbered sigc::slot# templates. - * Slots convert arbitrary functors to unified types which are opaque. - * sigc::slot itself is a functor or to be more precise a closure. It contains - * a single, arbitrary functor (or closure) that is executed in operator()(). - * - * The template arguments determine the function signature of operator()(): - * - @e T_return The return type of operator()().dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of operator()(). The default @p nil means no argument.]) - * - * To use, simply assign the desired functor to the slot. If the functor - * is not compatible with the parameter list defined with the template - * arguments, compiler errors are triggered. When called, the slot - * will invoke the functor with minimal copies. - * block() and unblock() can be used to temporarily block the functor's - * invocation from operator()(). - * - * @par Example: - * @code - * void foo(int) {} - * sigc::slot s = sigc::ptr_fun(&foo); - * s(19); - * @endcode - * - * sigc::slot<> is similar to std::function<>. If you're going to assign the - * resulting functor to a sigc::slot or connect it to a sigc::signal, it's better - * not to use std::function. It would become un unnecessary extra wrapper. - * - * @ingroup slot - */ -template ],[dnl - -/** Convenience wrapper for the numbered sigc::slot$1 template. - * See the base class for useful methods. - * This is the template specialization of the unnumbered sigc::slot - * template for $1 argument(s), specialized for different numbers of arguments - * This is possible because the template has default (nil) template types. -dnl * -dnl * @ingroup slot - */ -template ]) -class slot ifelse($1, $2,,[]) - : public slot$1 -{ -public: - typedef slot$1 parent_type; - - inline slot() {} - - /** Constructs a slot from an arbitrary functor. - * @param _A_func The desired functor the new slot should be assigned to. - */ - template - slot(const T_functor& _A_func) - : parent_type(_A_func) {} - - // Without static_cast parent_type(const T_functor& _A_func) - // is called instead of the copy constructor. - /** Constructs a slot, copying an existing one. - * @param src The existing slot to copy. - */ - slot(const slot& src) - : parent_type(static_cast(src)) {} - - // Without static_cast parent_type(const T_functor& _A_func) - // is called instead of the move constructor. - /** Constructs a slot, moving an existing one. - * If @p src is connected to a parent (e.g. a signal), it is copied, not moved. - * @param src The existing slot to move or copy. - */ - slot(slot&& src) - : parent_type(std::move(static_cast(src))) {} - - /** Overrides this slot, making a copy from another slot. - * @param src The slot from which to make a copy. - * @return @p this. - */ - slot& operator=(const slot& src) - { - parent_type::operator=(src); - return *this; - } - - /** Overrides this slot, making a move from another slot. - * If @p src is connected to a parent (e.g. a signal), it is copied, not moved. - * @param src The slot from which to move or copy. - * @return @p this. - */ - slot& operator=(slot&& src) - { - parent_type::operator=(std::move(src)); - return *this; - } -}; - -ifelse($1, $2,[dnl -#ifndef DOXYGEN_SHOULD_SKIP_THIS -//template specialization of visitor<>::do_visit_each<>(action, functor): -/** Performs a functor on each of the targets of a functor. - * - * There are three function overloads for sigc::slot. - * - * The first two overloads are very specialized. They handle the (probably unusual) - * case when the functor, stored in a slot, contains a slot. They are invoked from - * the constructor, destructor or destroy() method of typed_slot_rep. - * The first overload, called from the constructor of the outer slot, sets - * the outer slot as the parent of the inner slot. The second overload, called from - * the destructor or destroy() of the outer slot, unsets the parent of the inner slot. - * When an object referenced from the inner slot is deleted, the inner slot calls - * its slot_rep::disconnect(), which calls the outer slot's slot_rep::notify(). - * The outer slot is informed just as if one of its directly referenced objects - * had been deleted. Result: The outer slot is disconnected from its parent, - * if any (for instance a sigc::signal). - * See https://bugzilla.gnome.org/show_bug.cgi?id=755003 - * - * The third overload is identical to do_visit_each() in visitor's primary template. - * - * @ingroup slot - */ -template -struct visitor> -{ - static void do_visit_each(const internal::limit_derived_target& _A_action, - const slot& _A_target) - { - if (_A_target.rep_ && _A_target.rep_->parent_ == nullptr) - _A_target.rep_->set_parent(_A_action.action_.rep_, &internal::slot_rep::notify); - } - - static void do_visit_each(const internal::limit_derived_target& _A_action, - const slot& _A_target) - { - if (_A_target.rep_ && _A_target.rep_->parent_ == _A_action.action_.rep_) - _A_target.rep_->set_parent(nullptr, nullptr); - } - - template - static void do_visit_each(const T_action& _A_action, - const slot& _A_target) - { - _A_action(_A_target); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS -]) -]) -define([SLOT_CALL],[dnl -/** Abstracts functor execution. - * call_it() invokes a functor of type @e T_functor with a list of - * parameters whose types are given by the template arguments. - * address() forms a function pointer from call_it(). - * - * The following template arguments are used: - * - @e T_functor The functor type. - * - @e T_return The return type of call_it().dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of call_it().]) - * - */ -template -struct slot_call$1 -{ - /** Invokes a functor of type @p T_functor. - * @param rep slot_rep object that holds a functor of type @p T_functor.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the functor.]) - * @return The return values of the functor invocation. - */ - static T_return call_it(LIST(slot_rep* rep, LOOP(_R_(T_arg%1) a_%1, $1))) - { - typedef typed_slot_rep typed_slot; - typed_slot *typed_rep = static_cast(rep);dnl -ifelse($1,0,[ - return (typed_rep->functor_)(); -],[ - return (typed_rep->functor_).SIGC_WORKAROUND_OPERATOR_PARENTHESES - (LOOP(a_%1, $1)); -])dnl - } - - /** Forms a function pointer from call_it(). - * @return A function pointer formed from call_it(). - */ - static hook address() - { return reinterpret_cast(&call_it); } -}; - -]) - -divert(0)dnl -_FIREWALL([FUNCTORS_SLOT]) -#include -#include -#include -#include - -//TODO: See comment in functor_trait.h. -#if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO) - #define SIGC_NIL_HAS_BEEN_PUSHED 1 - #pragma push_macro("nil") - #undef nil -#endif - -namespace sigc { - -namespace internal { - -/** A typed slot_rep. - * A typed slot_rep holds a functor that can be invoked from - * slot::operator()(). visit_each() is used to visit the functor's - * targets that inherit trackable recursively and register the - * notification callback. Consequently the slot_rep object will be - * notified when some referred object is destroyed or overwritten. - */ -template -struct typed_slot_rep : public slot_rep -{ - typedef typed_slot_rep self; - - /* Use an adaptor type so that arguments can be passed as const references - * through explicit template instantiation from slot_call#::call_it() */ - typedef typename adaptor_trait::adaptor_type adaptor_type; - - /** The functor contained by this slot_rep object. */ - adaptor_type functor_; - - /** Constructs an invalid typed slot_rep object. - * The notification callback is registered using visit_each(). - * @param functor The functor contained by the new slot_rep object. - */ - inline typed_slot_rep(const T_functor& functor) - : slot_rep(nullptr, &destroy, &dup), functor_(functor) - { sigc::visit_each_type(slot_do_bind(this), functor_); } - - inline typed_slot_rep(const typed_slot_rep& cl) - : slot_rep(cl.call_, &destroy, &dup), functor_(cl.functor_) - { sigc::visit_each_type(slot_do_bind(this), functor_); } - - typed_slot_rep& operator=(const typed_slot_rep& src) = delete; - - typed_slot_rep(typed_slot_rep&& src) = delete; - typed_slot_rep& operator=(typed_slot_rep&& src) = delete; - - inline ~typed_slot_rep() - { - call_ = nullptr; - destroy_ = nullptr; - sigc::visit_each_type(slot_do_unbind(this), functor_); - } - - /** Detaches the stored functor from the other referred trackables and destroys it. - * This does not destroy the base slot_rep object. - */ - static void* destroy(void* data) - { - self* self_ = static_cast(reinterpret_cast(data)); - self_->call_ = nullptr; - self_->destroy_ = nullptr; - sigc::visit_each_type(slot_do_unbind(self_), self_->functor_); - self_->functor_.~adaptor_type(); - /* don't call disconnect() here: destroy() is either called - * a) from the parent itself (in which case disconnect() leads to a segfault) or - * b) from a parentless slot (in which case disconnect() does nothing) - */ - return nullptr; - } - - /** Makes a deep copy of the slot_rep object. - * Deep copy means that the notification callback of the new - * slot_rep object is registered in the referred trackables. - * @return A deep copy of the slot_rep object. - */ - static void* dup(void* data) - { - slot_rep* a_rep = reinterpret_cast(data); - return static_cast(new self(*static_cast(a_rep))); - } -}; - - -FOR(0,CALL_SIZE,[[SLOT_CALL(%1)]])dnl -} /* namespace internal */ - - -FOR(0,CALL_SIZE,[[SLOT_N(%1,CALL_SIZE)]]) -SLOT(CALL_SIZE,CALL_SIZE) -FOR(0,eval(CALL_SIZE-1),[[SLOT(%1,CALL_SIZE)]]) - -} /* namespace sigc */ - -#ifdef SIGC_NIL_HAS_BEEN_PUSHED - #undef SIGC_NIL_HAS_BEEN_PUSHED - #pragma pop_macro("nil") -#endif diff --git a/sigc++/functors/mem_fun.h b/sigc++/functors/mem_fun.h new file mode 100644 index 00000000..cdab86e7 --- /dev/null +++ b/sigc++/functors/mem_fun.h @@ -0,0 +1,290 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_FUNCTORS_MEM_FUN_H +#define SIGC_FUNCTORS_MEM_FUN_H +#include +#include +#include +#include +#include + +// implementation notes: +// - we do not use bind here, because it would introduce +// an extra copy and complicate the header include order if bind is +// to have automatic conversion for member pointers. + +namespace sigc +{ + +/** @defgroup mem_fun mem_fun() + * %mem_fun() creates a functor from a pointer to a method. + * + * Optionally, a reference to an object can be bound to the functor. + * + * @note If the object type inherits from sigc::trackable, and the + * functor returned from %mem_fun() is assigned to + * a @ref sigc::slot "sigc::slot", the functor + * will be automatically cleared when the object goes out of scope. Invoking + * that slot will then have no effect and will not try to use the destroyed + * instance. + * + * @par Example: + * @code + * struct foo : public sigc::trackable + * { + * void bar(int) {} + * }; + * foo my_foo; + * sigc::slot sl = sigc::mem_fun(my_foo, &foo::bar); + * // Note: f is not a slot. It will not be invalidated when my_foo is deleted. + * auto f = sigc::mem_fun(my_foo, &foo::bar); // Usually not what you want. + * @endcode + * + * For const methods %mem_fun() takes a const reference or pointer to an object. + * + * @par Example: + * @code + * struct foo : public sigc::trackable + * { + * void bar(int) const {} + * }; + * const foo my_foo; + * sigc::slot sl = sigc::mem_fun(my_foo, &foo::bar); + * @endcode + * + * If the member function pointer is to an overloaded type, you must specify + * the types using template arguments. + * + * @par Example: + * @code + * struct foo : public sigc::trackable + * { + * void bar(int) {} // choose this one + * void bar(float) {} + * void bar(int, int) {} + * }; + * foo my_foo; + * sigc::slot sl = sigc::mem_fun1(my_foo, &foo::bar); + * @endcode + * + * @ingroup sigcfunctors + */ + +template +class mem_functor +{ +public: + using object_type = typename internal::member_method_class::type; + + using function_type = T_func; + + using obj_type_with_modifier = typename std:: + conditional_t::value, const object_type, object_type>; + + /// Constructs an invalid functor. + mem_functor() : func_ptr_(nullptr) {} + + /** Constructs a mem_functor object that wraps the passed method. + * @param func Pointer to method will be invoked from operator()(). + */ + explicit mem_functor(function_type func) : func_ptr_(func) {} + + /** Execute the wrapped method operating on the passed instance. + * @param obj Reference to instance the method should operate on. + * @param a Arguments to be passed on to the method. + * @return The return value of the method invocation. + */ + decltype(auto) operator()(obj_type_with_modifier& obj, type_trait_take_t... a) const + { + return std::invoke(func_ptr_, obj, std::forward>(a)...); + } + +protected: + function_type func_ptr_; +}; + +template +class bound_mem_functor : mem_functor +{ + using base_type = mem_functor; + +public: + using function_type = typename base_type::function_type; + + using object_type = typename base_type::object_type; + + using obj_type_with_modifier = typename std:: + conditional_t::value, const object_type, object_type>; + using T_limit_reference = + typename std::conditional_t::value, + limit_reference, + limit_reference>; + + /** Constructs a bound_mem_functor object that wraps the passed method. + * @param obj Reference to instance the method will operate on. + * @param func Pointer to method will be invoked from operator()(). + */ + bound_mem_functor(obj_type_with_modifier& obj, function_type func) : base_type(func), obj_(obj) {} + + /** Execute the wrapped method operating on the stored instance. + * @param a Arguments to be passed on to the method. + * @return The return value of the method invocation. + */ + decltype(auto) operator()(type_trait_take_t... a) const + { + return std::invoke( + this->func_ptr_, obj_.invoke(), std::forward>(a)...); + } + + // protected: + // Reference to stored object instance. + // This is the handler object, such as TheObject in void TheObject::signal_handler(). + T_limit_reference obj_; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * The function overload for sigc::bound_$1mem_functor performs a functor + * on the object instance stored in the sigc::bound_$1mem_functor object. + * + * @ingroup mem_fun + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, + const bound_mem_functor& target) + { + sigc::visit_each(action, target.obj_); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +/** Creates a functor of type sigc::mem_functor which wraps a method. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) mem_fun(T_return (T_obj::*func)(T_arg...)) +{ + return mem_functor(func); +} + +/** Creates a functor of type sigc::const_mem_functor which wraps a const method. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) +mem_fun(T_return (T_obj::*func)(T_arg...) const) +{ + return mem_functor(func); +} + +/** Creates a functor of type sigc::volatile_mem_functor which wraps a volatile method. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) mem_fun(T_return (T_obj::*func)(T_arg...) volatile) +{ + return mem_functor(func); +} + +/** Creates a functor of type sigc::const_volatile_mem_functor which wraps a const volatile method. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) +mem_fun(T_return (T_obj::*func)(T_arg...) const volatile) +{ + return mem_functor(func); +} + +/** Creates a functor of type sigc::bound_mem_functor which encapsulates a method and an object + * instance. + * @param obj Reference to object instance the functor should operate on. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes @e func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) +mem_fun(/**/ T_obj& obj, T_return (T_obj2::*func)(T_arg...)) +{ + return bound_mem_functor(obj, func); +} + +/** Creates a functor of type sigc::bound_const_mem_functor which encapsulates a method and an + * object instance. + * @param obj Reference to object instance the functor should operate on. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes @e func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) +mem_fun(/*const*/ T_obj& obj, T_return (T_obj2::*func)(T_arg...) const) +{ + return bound_mem_functor(obj, func); +} + +/** Creates a functor of type sigc::bound_volatile_mem_functor which encapsulates a method and an + * object instance. + * @param obj Reference to object instance the functor should operate on. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes @e func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) +mem_fun(/**/ T_obj& obj, T_return (T_obj2::*func)(T_arg...) volatile) +{ + return bound_mem_functor(obj, func); +} + +/** Creates a functor of type sigc::bound_const_volatile_mem_functor which encapsulates a method and + * an object instance. + * @param obj Reference to object instance the functor should operate on. + * @param func Pointer to method that should be wrapped. + * @return Functor that executes @e func on invocation. + * + * @ingroup mem_fun + */ +template +inline decltype(auto) +mem_fun(/*const*/ T_obj& obj, T_return (T_obj2::*func)(T_arg...) const volatile) +{ + return bound_mem_functor(obj, func); +} + +} /* namespace sigc */ +#endif /* SIGC_FUNCTORS_MEM_FUN_H */ diff --git a/sigc++/functors/ptr_fun.h b/sigc++/functors/ptr_fun.h new file mode 100644 index 00000000..d94ed1d7 --- /dev/null +++ b/sigc++/functors/ptr_fun.h @@ -0,0 +1,113 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_FUNCTORS_PTR_FUN_H +#define SIGC_FUNCTORS_PTR_FUN_H +#include +#include +#include + +namespace sigc +{ + +/** @defgroup ptr_fun ptr_fun() + * %ptr_fun() creates a functor from a pointer to a function. + * + * @par Example: + * @code + * void foo(int) {} + * sigc::slot sl = sigc::ptr_fun(&foo); + * @endcode + * + * If the function pointer is to an overloaded type, you must specify + * the types using template arguments. + * + * @par Example: + * @code + * void foo(int) {} // choose this one + * void foo(float) {} + * void foo(int, int) {} + * sigc::slot sl = sigc::ptr_fun(&foo); + * @endcode + * + * %ptr_fun() can also be used to convert a pointer to a static member + * function to a functor, like so: + * + * @par Example: + * @code + * struct foo + * { + * static void bar(int) {} + * }; + * sigc::slot sl = sigc::ptr_fun(&foo::bar); + * @endcode + * + * @ingroup sigcfunctors + */ + +/** pointer_functor wraps existing non-member functions with, or without, arguments. + * Use the convenience function ptr_fun() to create an instance of pointer_functor. + * + * The following template arguments are used: + * - @e T_args... Argument types used in the definition of operator()(). + * - @e T_return The return type of operator()(). + * + * @ingroup ptr_fun + */ +template +class pointer_functor; + +template +class pointer_functor +{ + using function_type = T_return (*)(T_args...); + +protected: + function_type func_ptr_; + +public: + /// Constructs an invalid functor. + pointer_functor() = default; + + /** Constructs a pointer_functor2 object that wraps an existing function. + * @param func Pointer to function that will be invoked from operator()(). + */ + explicit pointer_functor(function_type func) : func_ptr_(func) {} + + /** Execute the wrapped function. + * @param a Arguments to be passed on to the function. + * @return The return value of the function invocation. + */ + T_return operator()(type_trait_take_t... a) const + { + return std::invoke(func_ptr_, std::forward>(a)...); + } +}; + +/** Creates a functor of type sigc::pointer_functor which wraps an existing non-member function. + * @param func Pointer to function that should be wrapped. + * @return Functor that executes @e func on invocation. + * + * @ingroup ptr_fun + */ +template +inline decltype(auto) ptr_fun(T_return (*func)(T_args...)) +{ + return pointer_functor(func); +} + +} /* namespace sigc */ +#endif /* SIGC_FUNCTORS_PTR_FUN_H */ diff --git a/sigc++/functors/slot.cc b/sigc++/functors/slot.cc deleted file mode 100644 index 5b9c92e2..00000000 --- a/sigc++/functors/slot.cc +++ /dev/null @@ -1,25 +0,0 @@ -// -*- c++ -*- -/* - * Copyright 2002, The libsigc++ Development Team - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include - -namespace sigc { - - -} /* namespace sigc */ diff --git a/sigc++/functors/slot.h b/sigc++/functors/slot.h new file mode 100644 index 00000000..ec7f2998 --- /dev/null +++ b/sigc++/functors/slot.h @@ -0,0 +1,329 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_FUNCTORS_SLOT_H +#define SIGC_FUNCTORS_SLOT_H + +#include +#include +#include +#include +#include +#include + +namespace sigc +{ + +namespace internal +{ + +// Conversion between different types of function pointers with +// reinterpret_cast can make gcc8 print a warning. +// https://github.com/libsigcplusplus/libsigcplusplus/issues/1 +// https://github.com/libsigcplusplus/libsigcplusplus/issues/8 +/** Returns the supplied function pointer, cast to a pointer to another function type. + * + * When a single reinterpret_cast between function pointer types causes a + * compiler warning or error, this function may work. + * + * Qualify calls with namespace names: sigc::internal::function_pointer_cast<>(). + * If you don't, indirect calls from another library that also contains a + * function_pointer_cast<>() (perhaps glibmm), can be ambiguous due to ADL + * (argument-dependent lookup). + */ +template +inline T_out +function_pointer_cast(T_in in) +{ + // The double reinterpret_cast suppresses a warning from gcc8 with the + // -Wcast-function-type option. + return reinterpret_cast(reinterpret_cast(in)); +} + +/** A typed slot_rep. + * A typed slot_rep holds a functor that can be invoked from + * slot::operator()(). visit_each() is used to visit the functor's + * targets that inherit trackable recursively and register the + * notification callback. Consequently the slot_rep object will be + * notified when some referred object is destroyed or overwritten. + */ +template +struct typed_slot_rep : public slot_rep +{ +private: + /* Use an adaptor type so that arguments can be passed as const references + * through explicit template instantiation from slot_call#::call_it() */ + using adaptor_type = typename adaptor_trait::adaptor_type; + +public: + /** The functor contained by this slot_rep object. */ + std::unique_ptr functor_; + + /** Constructs an invalid typed slot_rep object. + * The notification callback is registered using visit_each(). + * @param functor The functor contained by the new slot_rep object. + */ + inline explicit typed_slot_rep(const T_functor& functor) + : slot_rep(nullptr), functor_(std::make_unique(functor)) + { + sigc::visit_each_trackable(slot_do_bind(this), *functor_); + } + + inline typed_slot_rep(const typed_slot_rep& src) + : slot_rep(src.call_), functor_(std::make_unique(*src.functor_)) + { + sigc::visit_each_trackable(slot_do_bind(this), *functor_); + } + + typed_slot_rep& operator=(const typed_slot_rep& src) = delete; + + typed_slot_rep(typed_slot_rep&& src) = delete; + typed_slot_rep& operator=(typed_slot_rep&& src) = delete; + + ~typed_slot_rep() override + { + // Call destroy() non-virtually. + // It's unwise to make virtual calls in a constructor or destructor. + typed_slot_rep::destroy(); + } + +private: + /** Detaches the stored functor from the other referred trackables and destroys it. + * This does not destroy the base slot_rep object. + */ + void destroy() override + { + call_ = nullptr; + if (functor_) + { + sigc::visit_each_trackable(slot_do_unbind(this), *functor_); + functor_.reset(nullptr); + } + /* don't call disconnect() here: destroy() is either called + * a) from the parent itself (in which case disconnect() leads to a segfault) or + * b) from a parentless slot (in which case disconnect() does nothing) + */ + } + + /** Makes a deep copy of the slot_rep object. + * Deep copy means that the notification callback of the new + * slot_rep object is registered in the referred trackables. + * @return A deep copy of the slot_rep object. + */ + slot_rep* clone() const override { return new typed_slot_rep(*this); } +}; + +/** Abstracts functor execution. + * call_it() invokes a functor of type @e T_functor with a list of + * parameters whose types are given by the template arguments. + * address() forms a function pointer from call_it(). + * + * The following template arguments are used: + * - @e T_functor The functor type. + * - @e T_return The return type of call_it(). + * - @e T_arg Argument types used in the definition of call_it(). + * + */ +template +struct slot_call +{ + /** Invokes a functor of type @p T_functor. + * @param rep slot_rep object that holds a functor of type @p T_functor. + * @param a Arguments to be passed on to the functor. + * @return The return values of the functor invocation. + */ + static T_return call_it(slot_rep* rep, type_trait_take_t... a_) + { + auto typed_rep = static_cast*>(rep); + return (*typed_rep->functor_) + .template operator()...>( + std::forward>(a_)...); + } + + /** Forms a function pointer from call_it(). + * @return A function pointer formed from call_it(). + */ + static hook address() { return sigc::internal::function_pointer_cast(&call_it); } +}; + +} /* namespace internal */ + +// Because slot is opaque, visit_each() will not visit its internal members. +// Those members are not reachable by visit_each() after the slot has been +// constructed. But when a slot contains another slot, the outer slot will become +// the parent of the inner slot, with similar results. See the description of +// slot's specialization of the visitor struct. + +/** Converts an arbitrary functor to a unified type which is opaque. + * sigc::slot itself is a functor or, to be more precise, a closure. It contains + * a single, arbitrary functor (or closure) that is executed in operator()(). + * + * The template arguments determine the function signature of operator()(): + * - @e T_return The return type of operator()(). + * - @e T_arg Argument types used in the definition of operator()(). + * + * For instance, to declare a slot that returns void and takes two parameters + * of bool and int: + * @code + * sigc::slot some_slot; + * @endcode + * + * To use, simply assign the desired functor to the slot. If the functor + * is not compatible with the parameter list defined with the template + * arguments then compiler errors are triggered. When called, the slot + * will invoke the functor with minimal copies. + * block() and unblock() can be used to block the functor's invocation + * from operator()() temporarily. + * + * @ingroup slot + */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +class slot final { + static_assert(sizeof...(T_arg) < 0, "The slot syntax has been removed. Use the slot syntax."); +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +template +class slot : public slot_base +{ +public: + // TODO: using arg_type_ = type_trait_take_t; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +private: + using rep_type = internal::slot_rep; + +public: + using call_type = T_return (*)(rep_type*, type_trait_take_t...); +#endif + + /** Invoke the contained functor unless slot is in blocking state. + * @param a Arguments to be passed on to the functor. + * @return The return value of the functor invocation. + */ + inline T_return operator()(type_trait_take_t... a) const + { + if (!empty() && !blocked()) + { + return std::invoke(sigc::internal::function_pointer_cast(slot_base::rep_->call_), + slot_base::rep_, + std::forward>(a)...); + } + + return T_return(); + } + + inline slot() = default; + + // If you're tempted to add + // template, int> = 0> + // to the constructor, see https://github.com/libsigcplusplus/libsigcplusplus/issues/79 + // It doesn't work well when sigc::slot is combined with sigc::hide(). + + /** Constructs a slot from an arbitrary functor. + * @param func The desired functor the new slot should be assigned to. + */ + template + slot(const T_functor& func) : slot_base(new internal::typed_slot_rep(func)) + { + // The slot_base:: is necessary to stop the HP-UX aCC compiler from being confused. murrayc. + slot_base::rep_->call_ = internal::slot_call::address(); + } + + /** Constructs a slot, copying an existing one. + * @param src The existing slot to copy. + */ + slot(const slot& src) = default; + + /** Constructs a slot, moving an existing one. + * If @p src is connected to a parent (e.g. a signal), it is copied, not moved. + * @param src The existing slot to move or copy. + */ + slot(slot&& src) : slot_base(std::move(src)) {} + + /** Overrides this slot, making a copy from another slot. + * @param src The slot from which to make a copy. + * @return @p this. + */ + slot& operator=(const slot& src) = default; + + /** Overrides this slot, making a move from another slot. + * If @p src is connected to a parent (e.g. a signal), it is copied, not moved. + * @param src The slot from which to move or copy. + * @return @p this. + */ + slot& operator=(slot&& src) + { + slot_base::operator=(std::move(src)); + return *this; + } +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// template specialization of visitor<>::do_visit_each<>(action, functor): +/** Performs a functor on each of the targets of a functor. + * + * There are three function overloads for sigc::slot. + * + * The first two overloads are very specialized. They handle the (probably unusual) + * case when the functor, stored in a slot, contains a slot. They are invoked from + * the constructor, destructor or destroy() method of typed_slot_rep. + * The first overload, called from the constructor of the outer slot, sets + * the outer slot as the parent of the inner slot. The second overload, called from + * the destructor or destroy() of the outer slot, unsets the parent of the inner slot. + * When an object referenced from the inner slot is deleted, the inner slot calls + * its slot_rep::disconnect(), which calls the outer slot's slot_rep::notify_slot_rep_invalidated(). + * The outer slot is informed just as if one of its directly referenced objects + * had been deleted. Result: The outer slot is disconnected from its parent, + * if any (for instance a sigc::signal). + * See https://bugzilla.gnome.org/show_bug.cgi?id=755003 + * + * The third overload is identical to do_visit_each() in visitor's primary template. + * + * @ingroup slot + */ +template +struct visitor> +{ + static void do_visit_each(const internal::limit_trackable_target& action, + const slot& target) + { + if (target.rep_ && target.rep_->parent_ == nullptr) + target.rep_->set_parent( + action.action_.rep_, &internal::slot_rep::notify_slot_rep_invalidated); + } + + static void do_visit_each( + const internal::limit_trackable_target& action, + const slot& target) + { + if (target.rep_ && target.rep_->parent_ == action.action_.rep_) + target.rep_->unset_parent(); + } + + template + static void do_visit_each(const T_action& action, const slot& target) + { + action(target); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} /* namespace sigc */ + +#endif /* SIGC_FUNCTORS_SLOT_H */ diff --git a/sigc++/functors/slot_base.cc b/sigc++/functors/slot_base.cc index 1b8285ad..afd17940 100644 --- a/sigc++/functors/slot_base.cc +++ b/sigc++/functors/slot_base.cc @@ -1,5 +1,4 @@ -/* - * Copyright 2003, The libsigc++ Development Team +/* Copyright 2003 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,29 +11,21 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ #include +#include namespace { -// Used by slot_rep::notify() and slot_base::operator=(). They must be -// notified, if the slot_rep is deleted when they call disconnect(). -struct destroy_notify_struct +// Used by slot_base::set_parent() when a slot_base without a rep_ is assigned a parent. +class dummy_slot_rep : public sigc::internal::slot_rep { - destroy_notify_struct() noexcept : deleted_(false) { } - - static void* notify(void* data) noexcept - { - auto self_ = reinterpret_cast(data); - self_->deleted_ = true; - return nullptr; - } - - bool deleted_; +public: + dummy_slot_rep() : slot_rep(nullptr) {} + sigc::internal::slot_rep* clone() const override { return new dummy_slot_rep(); } + void destroy() override {} }; } // anonymous namespace @@ -44,18 +35,21 @@ namespace internal { // only MSVC needs this to guarantee that all new/delete are executed from the DLL module #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY -void* slot_rep::operator new(size_t size_) +void* +slot_rep::operator new(size_t size_) { return malloc(size_); } -void slot_rep::operator delete(void* p) +void +slot_rep::operator delete(void* p) { free(p); } #endif -void slot_rep::disconnect() +void +slot_rep::disconnect() { // Invalidate the slot. // _Must_ be done here because parent_ might defer the actual @@ -68,65 +62,55 @@ void slot_rep::disconnect() if (parent_) { auto data_ = parent_; - parent_ = nullptr; // Just a precaution. - (cleanup_)(data_); // Notify the parent (might lead to destruction of this!). + parent_ = nullptr; // Just a precaution. + (cleanup_)(data_); // Notify the parent (might lead to destruction of this!). } } -//static -void* slot_rep::notify(void* data) +// static +void +slot_rep::notify_slot_rep_invalidated(notifiable* data) { - auto self_ = reinterpret_cast(data); + auto self_ = static_cast(data); self_->call_ = nullptr; // Invalidate the slot. - + // Make sure we are notified if disconnect() deletes self_, which is trackable. - destroy_notify_struct notifier; - self_->add_destroy_notify_callback(¬ifier, destroy_notify_struct::notify); + sigc::internal::weak_raw_ptr notifier(self_); self_->disconnect(); // Disconnect the slot (might lead to deletion of self_!). - // If self_ has been deleted, the destructor has called destroy(). - if (!notifier.deleted_) + // If self_ has been deleted, then the weak_raw_ptr will have been invalidated. + if (notifier) { - self_->remove_destroy_notify_callback(¬ifier); - self_->destroy(); // Detach the stored functor from the other referred trackables and destroy it. - // destroy() might lead to deletion of self_. Bug #564005. + // Detach the stored functor from the other referred trackables and destroy it. + // destroy() might lead to deletion of self_. Bug #564005. + self_->destroy(); } - return nullptr; } } // namespace internal - -slot_base::slot_base() noexcept -: rep_(nullptr), - blocked_(false) -{} - -slot_base::slot_base(rep_type* rep) noexcept -: rep_(rep), - blocked_(false) -{} - -slot_base::slot_base(const slot_base& src) -: rep_(nullptr), - blocked_(src.blocked_) + +slot_base::slot_base() noexcept : rep_(nullptr), blocked_(false) {} + +slot_base::slot_base(rep_type* rep) noexcept : rep_(rep), blocked_(false) {} + +slot_base::slot_base(const slot_base& src) : rep_(nullptr), blocked_(src.blocked_) { if (src.rep_) { - //Check call_ so we can ignore invalidated slots. - //Otherwise, destroyed bound reference parameters (whose destruction caused the slot's invalidation) may be used during dup(). - //Note: I'd prefer to check somewhere during dup(). murrayc. + // Check call_ so we can ignore invalidated slots. + // Otherwise, destroyed bound reference parameters (whose destruction caused the slot's + // invalidation) may be used during clone(). + // Note: I'd prefer to check somewhere during clone(). murrayc. if (src.rep_->call_) - rep_ = src.rep_->dup(); + rep_ = src.rep_->clone(); else { - *this = slot_base(); //Return the default invalid slot. + *this = slot_base(); // Return the default invalid slot. } } } -slot_base::slot_base(slot_base&& src) -: rep_(nullptr), - blocked_(src.blocked_) +slot_base::slot_base(slot_base&& src) : rep_(nullptr), blocked_(src.blocked_) { if (src.rep_) { @@ -135,13 +119,13 @@ slot_base::slot_base(slot_base&& src) // src is connected to a parent, e.g. a sigc::signal. // Copy, don't move! See https://bugzilla.gnome.org/show_bug.cgi?id=756484 - //Check call_ so we can ignore invalidated slots. - //Otherwise, destroyed bound reference parameters (whose destruction - //caused the slot's invalidation) may be used during dup(). + // Check call_ so we can ignore invalidated slots. + // Otherwise, destroyed bound reference parameters (whose destruction + // caused the slot's invalidation) may be used during clone(). if (src.rep_->call_) - rep_ = src.rep_->dup(); + rep_ = src.rep_->clone(); else - blocked_ = false; //Return the default invalid slot. + blocked_ = false; // Return the default invalid slot. } else { @@ -149,7 +133,7 @@ slot_base::slot_base(slot_base&& src) src.rep_->notify_callbacks(); rep_ = src.rep_; - //Wipe src: + // Wipe src: src.rep_ = nullptr; src.blocked_ = false; } @@ -158,8 +142,7 @@ slot_base::slot_base(slot_base&& src) slot_base::~slot_base() { - if (rep_) - delete rep_; + delete rep_; } slot_base::operator bool() const noexcept @@ -167,30 +150,30 @@ slot_base::operator bool() const noexcept return rep_ != nullptr; } -void slot_base::delete_rep_with_check() +void +slot_base::delete_rep_with_check() { if (!rep_) return; // Make sure we are notified if disconnect() deletes rep_, which is trackable. - // Compare slot_rep::notify(). - destroy_notify_struct notifier; - rep_->add_destroy_notify_callback(¬ifier, destroy_notify_struct::notify); + // Compare slot_rep::notify_slot_rep_invalidated(). + sigc::internal::weak_raw_ptr notifier(rep_); rep_->disconnect(); // Disconnect the slot (might lead to deletion of rep_!). // If rep_ has been deleted, don't try to delete it again. // If it has been deleted, this slot_base has probably also been deleted, so // don't clear the rep_ pointer. It's the responsibility of the code that // deletes rep_ to either clear the rep_ pointer or delete this slot_base. - if (!notifier.deleted_) + if (notifier) { - rep_->remove_destroy_notify_callback(¬ifier); delete rep_; // Detach the stored functor from the other referred trackables and destroy it. rep_ = nullptr; } } -slot_base& slot_base::operator=(const slot_base& src) +slot_base& +slot_base::operator=(const slot_base& src) { if (src.rep_ == rep_) { @@ -205,7 +188,7 @@ slot_base& slot_base::operator=(const slot_base& src) return *this; } - auto new_rep_ = src.rep_->dup(); + auto new_rep_ = src.rep_->clone(); if (rep_) // Silently exchange the slot_rep. { @@ -219,7 +202,8 @@ slot_base& slot_base::operator=(const slot_base& src) return *this; } -slot_base& slot_base::operator=(slot_base&& src) +slot_base& +slot_base::operator=(slot_base&& src) { if (src.rep_ == rep_) { @@ -239,7 +223,7 @@ slot_base& slot_base::operator=(slot_base&& src) { // src is connected to a parent, e.g. a sigc::signal. // Copy, don't move! See https://bugzilla.gnome.org/show_bug.cgi?id=756484 - new_rep_ = src.rep_->dup(); + new_rep_ = src.rep_->clone(); } else { @@ -247,7 +231,7 @@ slot_base& slot_base::operator=(slot_base&& src) src.rep_->notify_callbacks(); new_rep_ = src.rep_; - //Wipe src: + // Wipe src: src.rep_ = nullptr; src.blocked_ = false; } @@ -261,43 +245,49 @@ slot_base& slot_base::operator=(slot_base&& src) return *this; } -void slot_base::set_parent(void* parent, void* (*cleanup)(void*)) const noexcept +void +slot_base::set_parent(notifiable* parent, notifiable::func_destroy_notify cleanup) const noexcept { - if (rep_) - rep_->set_parent(parent, cleanup); + if (!rep_) + rep_ = new dummy_slot_rep(); + rep_->set_parent(parent, cleanup); } -void slot_base::add_destroy_notify_callback(void* data, func_destroy_notify func) const +void +slot_base::add_destroy_notify_callback(notifiable* data, func_destroy_notify func) const { if (rep_) rep_->add_destroy_notify_callback(data, func); } -void slot_base::remove_destroy_notify_callback(void* data) const +void +slot_base::remove_destroy_notify_callback(notifiable* data) const { if (rep_) rep_->remove_destroy_notify_callback(data); } -bool slot_base::block(bool should_block) noexcept +bool +slot_base::block(bool should_block) noexcept { bool old = blocked_; blocked_ = should_block; return old; } -bool slot_base::unblock() noexcept +bool +slot_base::unblock() noexcept { return block(false); } -void slot_base::disconnect() +void +slot_base::disconnect() { if (rep_) rep_->disconnect(); } - /*bool slot_base::empty() const // having this function not inline is killing performance !!! { if (rep_ && !rep_->call_) @@ -308,4 +298,4 @@ void slot_base::disconnect() return (rep_ == nullptr); }*/ -} //namespace sigc +} // namespace sigc diff --git a/sigc++/functors/slot_base.h b/sigc++/functors/slot_base.h index d9697519..55b62ee2 100644 --- a/sigc++/functors/slot_base.h +++ b/sigc++/functors/slot_base.h @@ -1,5 +1,4 @@ -/* - * Copyright 2003, The libsigc++ Development Team +/* Copyright 2003 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,23 +11,21 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_SLOT_BASE_HPP_ -#define _SIGC_SLOT_BASE_HPP_ +#ifndef SIGC_SLOT_BASE_HPP +#define SIGC_SLOT_BASE_HPP #include #include -#include namespace sigc { -namespace internal { +namespace internal +{ -typedef void* (*hook)(void*); +using hook = void* (*)(void*); /** Internal representation of a slot. * Derivations of this class can be considered as a link @@ -40,20 +37,21 @@ typedef void* (*hook)(void*); * * The base class slot_rep serves the purpose to * - form a common pointer type (slot_rep*), - * - offer the possibility to create duplicates (dup()), - * - offer a notification callback (notify()), + * - offer the possibility to create duplicates (clone()), + * - offer a notification callback (notify_slot_rep_invalidated()), * - implement some of slot_base's interface that depends * on the notification callback, i.e. * -# the possibility to set a single parent with a callback - * (set_parent()) that is executed from notify(), + * (set_parent()) that is executed from notify_slot_rep_invalidated(), * -# a generic function pointer, call_, that is simply - * set to zero in notify() to invalidate the slot. + * set to zero in notify_slot_rep_invalidated() to invalidate the slot. * * slot_rep inherits trackable so that connection objects can * refer to the slot and are notified when the slot is destroyed. */ struct SIGC_API slot_rep : public trackable { +public: slot_rep(const slot_rep& src) = delete; slot_rep& operator=(const slot_rep& src) = delete; @@ -63,38 +61,13 @@ struct SIGC_API slot_rep : public trackable /* NB: Instead of slot_rep we could inherit slot_base from trackable. * However, a simple benchmark seems to indicate that this slows * down dereferencing of slot list iterators. Martin. */ + // TODO: Try this now? murrayc. - /// Callback that invokes the contained functor. - /* This can't be a virtual function since number of arguments - * must be flexible. We use function pointers to slot_call::call_it() - * instead. call_ is set to zero to indicate that the slot is invalid. - */ - hook call_; + inline slot_rep(hook call__) noexcept : call_(call__), cleanup_(nullptr), parent_(nullptr) {} - /// Callback that detaches the slot_rep object from referred trackables and destroys it. - /* This could be a replaced by a virtual dtor. However since this struct is - * crucual for the efficiency of the whole library we want to avoid this. - */ - hook destroy_; + virtual ~slot_rep() {} - /** Callback that makes a deep copy of the slot_rep object. - * @return A deep copy of the slot_rep object. - */ - hook dup_; - - /** Callback of parent_. */ - hook cleanup_; - - /** Parent object whose callback cleanup_ is executed on notification. */ - void* parent_; - - inline slot_rep(hook call__, hook destroy__, hook dup__) noexcept - : call_(call__), destroy_(destroy__), dup_(dup__), cleanup_(nullptr), parent_(nullptr) {} - - inline ~slot_rep() - { destroy(); } - - // only MSVC needs this to guarantee that all new/delete are executed from the DLL module +// only MSVC needs this to guarantee that all new/delete are executed from the DLL module #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY void* operator new(size_t size_); void operator delete(void* p); @@ -102,25 +75,32 @@ struct SIGC_API slot_rep : public trackable /** Destroys the slot_rep object (but doesn't delete it). */ - inline void destroy() - { if (destroy_) (*destroy_)(this); } + virtual void destroy() = 0; /** Makes a deep copy of the slot_rep object. * @return A deep copy of the slot_rep object. */ - inline slot_rep* dup() const - { return reinterpret_cast((*dup_)(const_cast(this))); } + virtual slot_rep* clone() const = 0; /** Set the parent with a callback. * slots have one parent exclusively. * @param parent The new parent. - * @param cleanup The callback to execute from notify(). + * @param cleanup The callback to execute from notify_slot_rep_invalidated(). */ - inline void set_parent(void* parent, hook cleanup) noexcept - { - parent_ = parent; - cleanup_ = cleanup; - } + inline void set_parent(notifiable* parent, notifiable::func_destroy_notify cleanup) noexcept + { + parent_ = parent; + cleanup_ = cleanup; + } + + /** See set_parent(). + * + */ + inline void unset_parent() noexcept + { + parent_ = nullptr; + cleanup_ = nullptr; + } /// Invalidates the slot and executes the parent's cleanup callback. void disconnect(); @@ -132,11 +112,25 @@ struct SIGC_API slot_rep : public trackable * referred object dying. * @param data The slot_rep object that is becoming invalid (@p this). */ - static void* notify(void* data); + static void notify_slot_rep_invalidated(notifiable* data); + +public: + /// Callback that invokes the contained functor. + /* This can't be a virtual function since number of arguments + * must be flexible. We use function pointers to slot_call::call_it() + * instead. call_ is set to zero to indicate that the slot is invalid. + */ + hook call_; + + /** Callback of parent_. */ + notifiable::func_destroy_notify cleanup_; + + /** Parent object whose callback cleanup_ is executed on notification. */ + notifiable* parent_; }; /** Functor used to add a dependency to a trackable. - * Consequently slot_rep::notify() gets executed when the + * Consequently slot_rep::notify_slot_rep_invalidated() gets executed when the * trackable is destroyed or overwritten. */ struct SIGC_API slot_do_bind @@ -147,13 +141,15 @@ struct SIGC_API slot_do_bind /** Construct a slot_do_bind functor. * @param rep The slot_rep object trackables should notify on destruction. */ - inline slot_do_bind(slot_rep* rep) noexcept : rep_(rep) {} + inline explicit slot_do_bind(slot_rep* rep) noexcept : rep_(rep) {} /** Adds a dependency to @p t. * @param t The trackable object to add a callback to. */ - inline void operator()(const trackable* t) const - { t->add_destroy_notify_callback(rep_, &slot_rep::notify); } + inline void operator()(const trackable& t) const + { + t.add_destroy_notify_callback(rep_, &slot_rep::notify_slot_rep_invalidated); + } }; /// Functor used to remove a dependency from a trackable. @@ -165,30 +161,31 @@ struct SIGC_API slot_do_unbind /** Construct a slot_do_unbind functor. * @param rep The slot_rep object trackables don't need to notify on destruction any more. */ - inline slot_do_unbind(slot_rep* rep) noexcept : rep_(rep) {} + inline explicit slot_do_unbind(slot_rep* rep) noexcept : rep_(rep) {} /** Removes a dependency from @p t. * @param t The trackable object to remove the callback from. */ - inline void operator()(const trackable* t) const - { t->remove_destroy_notify_callback(rep_); } + inline void operator()(const trackable& t) const { t.remove_destroy_notify_callback(rep_); } }; -} //namespace internal - +} // namespace internal /** @defgroup slot Slots * Slots are type-safe representations of callback methods and functions. * A slot can be constructed from any function object or function, regardless of * whether it is a global function, a member method, static, or virtual. * - * Use the sigc::mem_fun() and sigc::ptr_fun() template functions to get a sigc::slot, like so: + * @section slots-creating Creating Slots + * + * Use the sigc::mem_fun() or sigc::ptr_fun() template functions to get + * a @ref sigc::slot "sigc::slot", like so: * @code - * sigc::slot sl = sigc::mem_fun(someobj, &SomeClass::somemethod); + * sigc::slot sl = sigc::mem_fun(someobj, &SomeClass::somemethod); * @endcode * or * @code - * sigc::slot sl = sigc::ptr_fun(&somefunction); + * sigc::slot sl = sigc::ptr_fun(&somefunction); * @endcode * or, in gtkmm, * @code @@ -199,16 +196,29 @@ struct SIGC_API slot_do_unbind * * You can also pass slots as method parameters where you might normally pass a function pointer. * + * @section slots-auto-disconnect Member Methods and Automatic Disconnection + * + * See @ref mem_fun "sigc::mem_fun()" about deriving from sigc::trackable to prevent member + * methods from being called after the instance has been destroyed. + * + * @section slots-auto auto + * * sigc::mem_fun() and sigc::ptr_fun() return functors, but those functors are * not slots. * @code - * sigc::slot sl = sigc::mem_fun(someobj, &SomeClass::somemethod); + * sigc::slot sl = sigc::mem_fun(someobj, &SomeClass::somemethod); * @endcode * is not equivalent to * @code * auto sl = sigc::mem_fun(someobj, &SomeClass::somemethod); // Not a slot! * @endcode * + * If you don't explicitly use a @ref sigc::slot "sigc::slot" + * then the slot could call a method on an instance after it has been destroyed + * even if the method is in a class that derives from sigc::trackable. + * + * @section slots-with-lambdas C++ Lambdas + * * A C++11 lambda expression is a functor (function object). It is automatically * wrapped in a slot, if it is connected to a signal. * @code @@ -221,33 +231,31 @@ struct SIGC_API slot_do_unbind * @endcode * * If you connect a C++11 lambda expression or a std::function<> instance to - * a signal or assign it to a slot, - * - With libsigc++ versions before 2.6, if the return type is not void, - you must use the #SIGC_FUNCTORS_DEDUCE_RESULT_TYPE_WITH_DECLTYPE macro, - * - if your functor contains references to sigc::trackable derived objects, - * those objects will not be tracked, unless you also use sigc::track_obj(). + * a signal or assign it to a slot, if your functor contains references to + * sigc::trackable derived objects, those objects will not be tracked, + * unless you also use sigc::track_obj(). * * @ingroup sigcfunctors */ /** Base type for slots. - * slot_base integrates most of the interface of the derived - * sigc::slot templates. slots + * %slot_base integrates most of the interface of the derived + * @ref sigc::slot "sigc::slot" template. Slots * can be connected to signals, be disconnected at some later point * (disconnect()) and temporarily be blocked (block(), unblock()). * The validity of a slot can be tested with empty(). * * The internal representation of a sigc::internal::slot_rep derived - * type is built from slot_base's derivations. set_parent() is used to + * type is built from %slot_base's derivations. set_parent() is used to * register a notification callback that is executed when the slot gets * invalid. add_destroy_notify_callback() is used by connection objects * to add a notification callback that is executed on destruction. * * @ingroup slot */ -class SIGC_API slot_base : public functor_base +class SIGC_API slot_base { - typedef internal::slot_rep rep_type; + using rep_type = internal::slot_rep; // Move operations are not declared noexcept because // 1. they may copy instead of move @@ -284,6 +292,8 @@ class SIGC_API slot_base : public functor_base */ explicit operator bool() const noexcept; + using func_destroy_notify = notifiable::func_destroy_notify; + /** Sets the parent of this slot. * This function is used by signals to register a notification callback. * This notification callback is executed when the slot becomes invalid @@ -291,34 +301,31 @@ class SIGC_API slot_base : public functor_base * @param parent The new parent. * @param cleanup The notification callback. */ - void set_parent(void* parent, void* (*cleanup)(void*)) const noexcept; + void set_parent(notifiable* parent, notifiable::func_destroy_notify cleanup) const noexcept; - typedef trackable::func_destroy_notify func_destroy_notify; - /** Add a callback that is executed (notified) when the slot is detroyed. + /** Add a callback that is executed (notified) when the slot is destroyed. * This function is used internally by connection objects. * @param data Passed into func upon notification. * @param func Callback executed upon destruction of the object. */ - void add_destroy_notify_callback(void* data, func_destroy_notify func) const; + void add_destroy_notify_callback(notifiable* data, notifiable::func_destroy_notify func) const; /** Remove a callback previously installed with add_destroy_notify_callback(). * The callback is not executed. * @param data Parameter passed into previous call to add_destroy_notify_callback(). */ - void remove_destroy_notify_callback(void* data) const; + void remove_destroy_notify_callback(notifiable* data) const; /** Returns whether the slot is invalid. * @return @p true if the slot is invalid (empty). */ - inline bool empty() const noexcept - { return (!rep_ || !rep_->call_); } + inline bool empty() const noexcept { return (!rep_ || !rep_->call_); } /** Returns whether the slot is blocked. * @return @p true if the slot is blocked. */ - inline bool blocked() const noexcept - { return blocked_; } - + inline bool blocked() const noexcept { return blocked_; } + /** Sets the blocking state. * If @e should_block is @p true then the blocking state is set. * Subsequent calls to slot::operator()() don't invoke the functor @@ -339,9 +346,10 @@ class SIGC_API slot_base : public functor_base */ void disconnect(); -//The Tru64 and Solaris Forte 5.5 compilers needs this operator=() to be public. I'm not sure why, or why it needs to be protected usually. murrayc. -//See bug #168265. -//protected: + // The Tru64 and Solaris Forte 5.5 compilers needs this operator=() to be public. I'm not sure + // why, or why it needs to be protected usually. murrayc. + // See bug #168265. + // protected: /** Overrides this slot, making a copy from another slot. * @param src The slot from which to make a copy. * @return @p this. @@ -357,7 +365,7 @@ class SIGC_API slot_base : public functor_base public: // public to avoid template friend declarations /** Typed slot_rep object that contains a functor. */ - mutable rep_type *rep_; + mutable rep_type* rep_; /** Indicates whether the slot is blocked. */ bool blocked_; @@ -366,7 +374,6 @@ class SIGC_API slot_base : public functor_base void delete_rep_with_check(); }; -} //namespace sigc - -#endif //_SIGC_SLOT_BASE_HPP_ +} // namespace sigc +#endif // SIGC_SLOT_BASE_HPP diff --git a/sigc++/limit_reference.h b/sigc++/limit_reference.h new file mode 100644 index 00000000..f55330d8 --- /dev/null +++ b/sigc++/limit_reference.h @@ -0,0 +1,148 @@ +/* Copyright 2005 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_LIMIT_REFERENCE_H +#define SIGC_LIMIT_REFERENCE_H + +#include +#include +#include + +namespace sigc +{ + +/** A limit_reference object stores a reference (Foo&), but makes sure that, + * if Foo inherits from sigc::trackable, then visit_each<>() will "limit" itself to the + * sigc::trackable reference instead of the derived reference. This avoids use of + * a reference to the derived type when the derived destructor has run. That can be + * a problem when using virtual inheritance. + * + * If Foo inherits from trackable then both the derived reference and the + * sigc::trackable reference are stored, so we can later retrieve the sigc::trackable + * reference without doing an implicit conversion. To retrieve the derived reference + * (so that you invoke methods or members of it), use invoke(). To retrieve the trackable + * reference (so that you can call visit_each() on it), you use visit(). + * + * If Foo does not inherit from sigc::trackable then invoke() and visit() just return the + * derived reference. + * + * This is used for bound (sigc::bind) slot parameters (via bound_argument), bound return values, + * and, with mem_fun(), the reference to the handling object. + * + * - @e T_type The type of the reference. + */ +template>::value> +class limit_reference +{ +public: + using reference_type = typename std::remove_volatile_t; + + limit_reference() = delete; + + /** Constructor. + * @param target The reference to limit. + */ + explicit limit_reference(reference_type& target) : visited(target) {} + + limit_reference(const limit_reference& src) = default; + limit_reference& operator=(const limit_reference& src) = default; + + limit_reference(limit_reference&& src) = default; + limit_reference& operator=(limit_reference&& src) = default; + + /** Retrieve the entity to visit for visit_each(). + * Depending on the template specialization, this is either a derived reference, or + * sigc::trackable& if T_type derives from sigc::trackable. + * @return The reference. + */ + inline const reference_type& visit() const { return visited; } + + /** Retrieve the reference. + * This is always a reference to the derived instance. + * @return The reference. + */ + inline T_type& invoke() const { return visited; } + +private: + /** The reference. + */ + reference_type& visited; +}; + +/** limit_reference object for a class that derives from trackable. + * - @e T_type The type of the reference. + */ +template +class limit_reference +{ +public: + using reference_type = typename std::remove_volatile_t; + + /** Constructor. + * @param target The reference to limit. + */ + limit_reference(reference_type& target) : visited(target), invoked(target) {} + + /** Retrieve the entity to visit for visit_each(). + * Depending on the template specialization, this is either a derived reference, or + * sigc::trackable& if T_type derives from sigc::trackable. + * @return The reference. + */ + inline const trackable& visit() const { return visited; } + + /** Retrieve the reference. + * This is always a reference to the derived instance. + * @return The reference. + */ + inline T_type& invoke() const { return invoked; } + +private: + using trackable_type = + typename std::conditional_t::value, const trackable, trackable>; + + /** The trackable reference. + */ + trackable_type& visited; + + /** The reference. + */ + reference_type& invoked; +}; + +#ifndef DOXYGEN_SHOULD_SKIP_THIS +/** Implementation of visitor specialized for the $1limit_reference + * class, to call visit_each() on the entity returned by the $1limit_reference's + * visit() method. + * @tparam T_type The type of the reference + * @tparam T_action The type of functor to invoke. + * @param action The functor to invoke. + * @param target The visited instance. + */ +template +struct visitor> +{ + template + static void do_visit_each(const T_action& action, const limit_reference& target) + { + sigc::visit_each(action, target.visit()); + } +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +} /* namespace sigc */ + +#endif /* SIGC_LIMIT_REFERENCE_H */ diff --git a/sigc++/macros/limit_reference.h.m4 b/sigc++/macros/limit_reference.h.m4 deleted file mode 100644 index 679a86ca..00000000 --- a/sigc++/macros/limit_reference.h.m4 +++ /dev/null @@ -1,158 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([LIMIT_REFERENCE],[dnl -/** A [$1]limit_reference object stores a reference (Foo&), but make sure that, - * if Foo inherits from sigc::trackable, then visit_each<>() will "limit" itself to the - * sigc::trackable reference instead of the derived reference. This avoids use of - * a reference to the derived type when the derived destructor has run. That can be - * a problem when using virtual inheritance. - * - * If Foo inherits from trackable then both the derived reference and the - * sigc::trackable reference are stored, so we can later retrieve the sigc::trackable - * reference without doing an implicit conversion. To retrieve the derived reference - * (so that you invoke methods or members of it), use invoke(). To retrieve the trackable - * reference (so that you can call visit_each() on it), you use visit(). - * - * If Foo does not inherit from sigc::trackable then invoke() and visit() just return the - * derived reference. - * - * This is used for bound (sigc::bind) slot parameters (via bound_argument), bound return values, - * and, with mem_fun(), the reference to the handling object. - * - * - @e T_type The type of the reference. - */ -template ::value> -class [$1]limit_reference -{ -public: - /** Constructor. - * @param _A_target The reference to limit. - */ - [$1]limit_reference([$2]T_type& _A_target) - : visited(_A_target) - {} - - /** Retrieve the entity to visit for visit_each(). - * Depending on the template specialization, this is either a derived reference, or sigc::trackable& if T_type derives from sigc::trackable. - * @return The reference. - */ - inline const T_type& visit() const - { return visited; } - - /** Retrieve the reference. - * This is always a reference to the derived instance. - * @return The reference. - */ - inline [$3]T_type& invoke() const - { return visited; } - -private: - /** The reference. - */ - [$2]T_type& visited; -}; - -/** [$1]limit_reference object for a class that derives from trackable. - * - @e T_type The type of the reference. - */ -template -class [$1]limit_reference -{ -public: - /** Constructor. - * @param _A_target The reference to limit. - */ - [$1]limit_reference([$2]T_type& _A_target) - : visited(_A_target), - invoked(_A_target) - {} - - /** Retrieve the entity to visit for visit_each(). - * Depending on the template specialization, this is either a derived reference, or sigc::trackable& if T_type derives from sigc::trackable. - * @return The reference. - */ - inline const trackable& visit() const - { return visited; } - - /** Retrieve the reference. - * This is always a reference to the derived instance. - * @return The reference. - */ - inline [$3]T_type& invoke() const - { return invoked; } - -private: - /** The trackable reference. - */ - [$2]trackable& visited; - - /** The reference. - */ - [$2]T_type& invoked; -}; - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -/** Implementation of visitor specialized for the [$1]limit_reference - * class, to call visit_each() on the entity returned by the [$1]limit_reference's - * visit() method. - * @tparam T_type The type of the reference. - * @tparam T_action The type of functor to invoke. - * @param _A_action The functor to invoke. - * @param _A_target The visited instance. - */ -template -struct visitor<[$1]limit_reference > -{ - template - static void do_visit_each(const T_action& _A_action, - const [$1]limit_reference& _A_target) - { - sigc::visit_each(_A_action, _A_target.visit()); - } -}; -#endif // DOXYGEN_SHOULD_SKIP_THIS -]) - -divert(0) - -_FIREWALL([LIMIT_REFERENCE]) - -#include -#include -#include - -namespace sigc { - -LIMIT_REFERENCE([],[],[])dnl - - -LIMIT_REFERENCE([const_],[const ],[const ])dnl - - -LIMIT_REFERENCE([volatile_],[],[volatile ])dnl - - -LIMIT_REFERENCE([const_volatile_],[const ],[const volatile ])dnl - -} /* namespace sigc */ - diff --git a/sigc++/macros/signal.h.m4 b/sigc++/macros/signal.h.m4 deleted file mode 100644 index b9e2a2bb..00000000 --- a/sigc++/macros/signal.h.m4 +++ /dev/null @@ -1,1170 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -divert(-1) - -include(template.macros.m4) - -define([SIGNAL_EMIT_N],[dnl -/** Abstracts signal emission. - * This template implements the emit() function of signal$1. - * Template specializations are available to optimize signal - * emission when no accumulator is used, for example when the template - * argument @e T_accumulator is @p nil. - */ -template -struct signal_emit$1 -{ - typedef signal_emit$1 self_type; - typedef typename T_accumulator::result_type result_type; - typedef slot slot_type; - typedef internal::slot_iterator_buf slot_iterator_buf_type; - typedef internal::slot_reverse_iterator_buf slot_reverse_iterator_buf_type; - typedef signal_impl::const_iterator_type iterator_type; - -ifelse($1,0,,[dnl - /** Instantiates the class. - * The parameters are stored in member variables. operator()() passes - * the values on to some slot. - */ -])dnl - signal_emit$1(LOOP(type_trait_take_t _A_a%1, $1)) ifelse($1,0,,[ - : LOOP(_A_a%1_(_A_a%1), $1)]) {} - -ifelse($1,0,[dnl - /** Invokes a slot.],[ - /** Invokes a slot using the buffered parameter values.]) - * @param _A_slot Some slot to invoke. - * @return The slot's return value. - */ - T_return operator()(const slot_type& _A_slot) const - { return (reinterpret_cast(_A_slot.rep_->call_))(LIST(_A_slot.rep_, LOOP(_A_a%1_, $1))); } -dnl T_return operator()(const slot_type& _A_slot) const -dnl { return _A_slot(LOOP(_A_a%1_, $1)); } - - /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl -ifelse($1,0,,[ - * The arguments are buffered in a temporary instance of signal_emit$1.]) -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - * @return The accumulated return values of the slot invocations as processed by the accumulator. - */ - static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t _A_a%1, $1))) - { - T_accumulator accumulator; - - if (!impl) - return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type()); - - signal_exec exec(impl); - temp_slot_list slots(impl->slots_); - - self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]); - return accumulator(slot_iterator_buf_type(slots.begin(), &self), - slot_iterator_buf_type(slots.end(), &self)); - } - - /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl -ifelse($1,0,,[ - * The arguments are buffered in a temporary instance of signal_emit$1.]) -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - * @return The accumulated return values of the slot invocations as processed by the accumulator. - */ - static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t _A_a%1, $1))) - { - T_accumulator accumulator; - - if (!impl) - return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type()); - - signal_exec exec(impl); - temp_slot_list slots(impl->slots_); - - self_type self ifelse($1,0,,[(LOOP(_A_a%1, $1))]); - return accumulator(slot_reverse_iterator_buf_type(slots.end(), &self), - slot_reverse_iterator_buf_type(slots.begin(), &self)); - } -dnl - FOR(1, $1,[ - type_trait_take_t _A_a%1_;]) -}; - -/** Abstracts signal emission. - * This template specialization implements an optimized emit() - * function for the case that no accumulator is used. - */ -template -struct signal_emit$1 -{ - typedef signal_emit$1 self_type; - typedef T_return result_type; - typedef slot slot_type; - typedef signal_impl::const_iterator_type iterator_type; - typedef typename slot_type::call_type call_type; - - /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl -ifelse($1,0,,[ - * The arguments are passed directly on to the slots.]) - * The return value of the last slot invoked is returned. - * @param first An iterator pointing to the first slot in the list. - * @param last An iterator pointing to the last slot in the list.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - * @return The return value of the last slot invoked. - */ - static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t _A_a%1, $1))) - { - if (!impl || impl->slots_.empty()) - return T_return(); - - signal_exec exec(impl); - T_return r_ = T_return(); - - //Use this scope to make sure that "slots" is destroyed before "exec" is destroyed. - //This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249 - { - temp_slot_list slots(impl->slots_); - iterator_type it = slots.begin(); - for (; it != slots.end(); ++it) - if (!it->empty() && !it->blocked()) break; - - if (it == slots.end()) - return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows: - - r_ = (reinterpret_cast(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1))); - for (++it; it != slots.end(); ++it) - { - if (it->empty() || it->blocked()) - continue; - r_ = (reinterpret_cast(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1))); - } - } - - return r_; - } - - /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl -ifelse($1,0,,[ - * The arguments are passed directly on to the slots.]) - * The return value of the last slot invoked is returned. - * @param first An iterator pointing to the first slot in the list. - * @param last An iterator pointing to the last slot in the list.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - * @return The return value of the last slot invoked. - */ - static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t _A_a%1, $1))) - { - if (!impl || impl->slots_.empty()) - return T_return(); - - signal_exec exec(impl); - T_return r_ = T_return(); - - //Use this scope to make sure that "slots" is destroyed before "exec" is destroyed. - //This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249 - { -#ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR - typedef std::reverse_iterator reverse_iterator_type; -#else - typedef std::reverse_iterator reverse_iterator_type; -#endif - - temp_slot_list slots(impl->slots_); - reverse_iterator_type it(slots.end()); - for (; it != reverse_iterator_type(slots.begin()); ++it) - if (!it->empty() && !it->blocked()) break; - - if (it == reverse_iterator_type(slots.begin())) - return T_return(); // note that 'T_return r_();' doesn't work => define 'r_' after this line and initialize as follows: - - r_ = (reinterpret_cast(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1))); - for (++it; it != reverse_iterator_type(slots.begin()); ++it) - { - if (it->empty() || it->blocked()) - continue; - r_ = (reinterpret_cast(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1))); - } - } - - return r_; - } -}; - -/** Abstracts signal emission. - * This template specialization implements an optimized emit() - * function for the case that no accumulator is used and the - * return type is @p void. - */ -template -struct signal_emit$1 -{ - typedef signal_emit$1 self_type; - typedef void result_type; - typedef slot slot_type; - typedef signal_impl::const_iterator_type iterator_type; - typedef ifelse($1,0,void (*call_type)(slot_rep*),typename slot_type::call_type call_type); - - /** Executes a list of slots using an accumulator of type @e T_accumulator.dnl -ifelse($1,0,,[ - * The arguments are passed directly on to the slots.]) - * @param first An iterator pointing to the first slot in the list. - * @param last An iterator pointing to the last slot in the list.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - */ - static result_type emit(LIST(signal_impl* impl, LOOP(type_trait_take_t _A_a%1, $1))) - { - if (!impl || impl->slots_.empty()) return; - signal_exec exec(impl); - temp_slot_list slots(impl->slots_); - - for (iterator_type it = slots.begin(); it != slots.end(); ++it) - { - if (it->empty() || it->blocked()) - continue; - (reinterpret_cast(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1))); - } - } - - /** Executes a list of slots using an accumulator of type @e T_accumulator in reverse order.dnl -ifelse($1,0,,[ - * The arguments are passed directly on to the slots.]) - * @param first An iterator pointing to the first slot in the list. - * @param last An iterator pointing to the last slot in the list.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - */ - static result_type emit_reverse(LIST(signal_impl* impl, LOOP(type_trait_take_t _A_a%1, $1))) - { - if (!impl || impl->slots_.empty()) return; - signal_exec exec(impl); - temp_slot_list slots(impl->slots_); - -#ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR - typedef std::reverse_iterator reverse_iterator_type; -#else - typedef std::reverse_iterator reverse_iterator_type; -#endif - for (reverse_iterator_type it = reverse_iterator_type(slots.end()); it != reverse_iterator_type(slots.begin()); ++it) - { - if (it->empty() || it->blocked()) - continue; - (reinterpret_cast(it->rep_->call_))(LIST(it->rep_, LOOP(_A_a%1, $1))); - } - } -}; - -]) -define([SIGNAL_N],[dnl -/** Signal declaration. - * signal$1 can be used to connect() slots that are invoked - * during subsequent calls to emit(). Any functor or slot - * can be passed into connect(). It is converted into a slot - * implicitly. - * - * If you want to connect one signal to another, use make_slot() - * to retrieve a functor that emits the signal when invoked. - * - * Be careful if you directly pass one signal into the connect() - * method of another: a shallow copy of the signal is made and - * the signal's slots are not disconnected until both the signal - * and its clone are destroyed, which is probably not what you want! - * - * An STL-style list interface for the signal's list of slots - * can be retrieved with slots(). This interface supports - * iteration, insertion and removal of slots. - * - * The following template arguments are used: - * - @e T_return The desired return type for the emit() function (may be overridden by the accumulator).dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of emit().]) - * - @e T_accumulator The accumulator type used for emission. The default - * @p nil means that no accumulator should be used, for example if signal - * emission returns the return value of the last slot invoked. - * - * You should use the more convenient unnumbered sigc::signal template. - * - * @ingroup signal - */ -template -class signal$1 - : public signal_base -{ -public: - typedef internal::signal_emit$1 emitter_type; - typedef typename emitter_type::result_type result_type; - typedef slot slot_type; - typedef slot_list slot_list_type; - typedef typename slot_list_type::iterator iterator; - typedef typename slot_list_type::const_iterator const_iterator; - typedef typename slot_list_type::reverse_iterator reverse_iterator; - typedef typename slot_list_type::const_reverse_iterator const_reverse_iterator; - - /** Add a slot to the list of slots. - * Any functor or slot may be passed into connect(). - * It will be converted into a slot implicitly. - * The returned iterator may be stored for disconnection - * of the slot at some later point. It stays valid until - * the slot is removed from the list of slots. The iterator - * can also be implicitly converted into a sigc::connection object - * that may be used safely beyond the life time of the slot. - * - * std::function<> and C++11 lambda expressions are functors. - * These are examples of functors that can be connected to a signal. - * - * %std::bind() creates a functor, but this functor typically has an - * %operator()() which is a variadic template. - * Our functor_trait can't deduce the result type - * of such a functor. If you first assign the return value of %std::bind() - * to a std::function, you can connect the std::function to a signal. - * - * @param slot_ The slot to add to the list of slots. - * @return An iterator pointing to the new slot in the list. - */ - iterator connect(const slot_type& slot_) - { return iterator(signal_base::connect(static_cast(slot_))); } - - /** Add a slot to the list of slots. - * @see connect(const slot_type& slot_). - * - * @newin{2,8} - */ - iterator connect(slot_type&& slot_) - { return iterator(signal_base::connect(std::move(static_cast(slot_)))); } - - /** Triggers the emission of the signal. - * During signal emission all slots that have been connected - * to the signal are invoked unless they are manually set into - * a blocking state. The parameters are passed on to the slots. - * If @e T_accumulated is not @p nil, an accumulator of this type - * is used to process the return values of the slot invocations. - * Otherwise, the return value of the last slot invoked is returned.dnl -FOR(1, $1,[ - * @param _A_a%1 Argument to be passed on to the slots.]) - * @return The accumulated return values of the slot invocations. - */ - result_type emit(LOOP(type_trait_take_t _A_a%1, $1)) const - { return emitter_type::emit(LIST(impl_, LOOP(_A_a%1, $1))); } - - /** Triggers the emission of the signal in reverse order (see emit()). */ - result_type emit_reverse(LOOP(type_trait_take_t _A_a%1, $1)) const - { return emitter_type::emit_reverse(LIST(impl_, LOOP(_A_a%1, $1))); } - - /** Triggers the emission of the signal (see emit()). */ - result_type operator()(LOOP(type_trait_take_t _A_a%1, $1)) const - { return emit(LOOP(_A_a%1, $1)); } - - /** Creates a functor that calls emit() on this signal. - * @code - * sigc::mem_fun(mysignal, &sigc::signal$1::emit) - * @endcode - * yields the same result. - * @return A functor that calls emit() on this signal. - */ - bound_const_mem_functor$1, $1))> make_slot() const - { return bound_const_mem_functor$1, $1))>(this, &signal$1::emit); } - - /** Creates an STL-style interface for the signal's list of slots. - * This interface supports iteration, insertion and removal of slots. - * @return An STL-style interface for the signal's list of slots. - */ - slot_list_type slots() - { return slot_list_type(impl()); } - - /** Creates an STL-style interface for the signal's list of slots. - * This interface supports iteration, insertion and removal of slots. - * @return An STL-style interface for the signal's list of slots. - */ - const slot_list_type slots() const - { return slot_list_type(const_cast(this)->impl()); } - - signal$1() {} - - signal$1(const signal$1& src) - : signal_base(src) {} - - signal$1(signal$1&& src) - : signal_base(std::move(src)) {} - - signal$1& operator=(const signal$1& src) - { - signal_base::operator=(src); - return *this; - } - - signal$1& operator=(signal$1&& src) - { - signal_base::operator=(std::move(src)); - return *this; - } -}; - -]) -define([SIGNAL],[dnl -ifelse($1, $2,[dnl -/** Convenience wrapper for the numbered sigc::signal# templates. - * signal can be used to connect() slots that are invoked - * during subsequent calls to emit(). Any functor or slot - * can be passed into connect(). It is converted into a slot - * implicitly. - * - * If you want to connect one signal to another, use make_slot() - * to retrieve a functor that emits the signal when invoked. - * - * Be careful if you directly pass one signal into the connect() - * method of another: a shallow copy of the signal is made and - * the signal's slots are not disconnected until both the signal - * and its clone are destroyed, which is probably not what you want! - * - * An STL-style list interface for the signal's list of slots - * can be retrieved with slots(). This interface supports - * iteration, insertion and removal of slots. - * - * The template arguments determine the function signature of - * the emit() function: - * - @e T_return The desired return type of the emit() function.dnl -FOR(1,$1,[ - * - @e T_arg%1 Argument type used in the definition of emit(). The default @p nil means no argument.]) - * - * To specify an accumulator type the nested class signal::accumulated can be used. - * - * @par Example: - * @code - * void foo(int) {} - * sigc::signal sig; - * sig.connect(sigc::ptr_fun(&foo)); - * sig.emit(19); - * @endcode - * - * @ingroup signal - */ -template ],[dnl - -/** Convenience wrapper for the numbered sigc::signal$1 template. - * See the base class for useful methods. - * This is the template specialization of the unnumbered sigc::signal - * template for $1 argument(s). -ifelse($1, $2,[dnl - * - * @ingroup signal -])dnl - */ -template ]) -class signal ifelse($1, $2,,[]) - : public signal$1 -{ -public: -ifelse($1, $2,[dnl - /** Convenience wrapper for the numbered sigc::signal# templates. - * Like sigc::signal but the additional template parameter @e T_accumulator - * defines the accumulator type that should be used. - * - * An accumulator is a functor that uses a pair of special iterators - * to step through a list of slots and calculate a return value - * from the results of the slot invokations. The iterators' operator*() - * executes the slot. The return value is buffered, so that in an expression - * like @code a = (*i) * (*i); @endcode the slot is executed only once. - * The accumulator must define its return value as @p result_type. - * - * @par Example 1: - * This accumulator calculates the arithmetic mean value: - * @code - * struct arithmetic_mean_accumulator - * { - * typedef double result_type; - * template - * result_type operator()(T_iterator first, T_iterator last) const - * { - * result_type value_ = 0; - * int n_ = 0; - * for (; first != last; ++first, ++n_) - * value_ += *first; - * return value_ / n_; - * } - * }; - * @endcode - * - * @par Example 2: - * This accumulator stops signal emission when a slot returns zero: - * @code - * struct interruptable_accumulator - * { - * typedef bool result_type; - * template - * result_type operator()(T_iterator first, T_iterator last) const - * { - * for (; first != last; ++first, ++n_) - * if (!*first) return false; - * return true; - * } - * }; - * @endcode - * - * @ingroup signal -],[ - /** Convenience wrapper for the numbered sigc::signal$1 template. - * Like sigc::signal but the additional template parameter @e T_accumulator - * defines the accumulator type that should be used. -])dnl - */ - template - class accumulated - : public signal$1 - { - public: - accumulated() {} - accumulated(const accumulated& src) - : signal$1(src) {} - }; - - signal() {} - - signal(const signal& src) - : signal$1(src) {} - - signal(signal&& src) - : signal$1(std::move(src)) {} - - signal& operator=(const signal& src) - { - signal$1::operator=(src); - return *this; - } - - signal& operator=(signal&& src) - { - signal$1::operator=(std::move(src)); - return *this; - } -}; - -]) - -divert(0) -#ifndef _SIGC_SIGNAL_H_ -#define _SIGC_SIGNAL_H_ - -#include -#include -#include -#include -#include -#include - -//TODO: See comment in functor_trait.h. -#if defined(nil) && defined(SIGC_PRAGMA_PUSH_POP_MACRO) - #define SIGC_NIL_HAS_BEEN_PUSHED 1 - #pragma push_macro("nil") - #undef nil -#endif - -//SIGC_TYPEDEF_REDEFINE_ALLOWED: -// TODO: This should have its own test, but I can not create one that gives the error instead of just a warning. murrayc. -// I have just used this because there is a correlation between these two problems. -#ifdef SIGC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - //Compilers, such as older versions of SUN Forte C++, that do not allow this also often - //do not allow a typedef to have the same name as a class in the typedef's definition. - //For Sun Forte CC 5.7 (SUN Workshop 10), comment this out to fix the build. - #define SIGC_TYPEDEF_REDEFINE_ALLOWED 1 -#endif - -namespace sigc { - -/** STL-style iterator for slot_list. - * - * @ingroup signal - */ -template -struct slot_iterator -{ - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - typedef T_slot slot_type; - - typedef T_slot value_type; - typedef T_slot* pointer; - typedef T_slot& reference; - - typedef typename internal::signal_impl::iterator_type iterator_type; - - slot_iterator() - {} - - explicit slot_iterator(const iterator_type& i) - : i_(i) {} - - reference operator*() const - { return static_cast(*i_); } - - pointer operator->() const - { return &(operator*()); } - - slot_iterator& operator++() - { - ++i_; - return *this; - } - - slot_iterator operator++(int) - { - slot_iterator __tmp(*this); - ++i_; - return __tmp; - } - - slot_iterator& operator--() - { - --i_; - return *this; - } - - slot_iterator operator--(int) - { - slot_iterator __tmp(*this); - --i_; - return __tmp; - } - - bool operator == (const slot_iterator& other) const - { return i_ == other.i_; } - - bool operator != (const slot_iterator& other) const - { return i_ != other.i_; } - - iterator_type i_; -}; - -/** STL-style const iterator for slot_list. - * - * @ingroup signal - */ -template -struct slot_const_iterator -{ - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - typedef T_slot slot_type; - - typedef T_slot value_type; - typedef const T_slot* pointer; - typedef const T_slot& reference; - - typedef typename internal::signal_impl::const_iterator_type iterator_type; - - slot_const_iterator() - {} - - explicit slot_const_iterator(const iterator_type& i) - : i_(i) {} - - reference operator*() const - { return static_cast(*i_); } - - pointer operator->() const - { return &(operator*()); } - - slot_const_iterator& operator++() - { - ++i_; - return *this; - } - - slot_const_iterator operator++(int) - { - slot_const_iterator __tmp(*this); - ++i_; - return __tmp; - } - - slot_const_iterator& operator--() - { - --i_; - return *this; - } - - slot_const_iterator operator--(int) - { - slot_const_iterator __tmp(*this); - --i_; - return __tmp; - } - - bool operator == (const slot_const_iterator& other) const - { return i_ == other.i_; } - - bool operator != (const slot_const_iterator& other) const - { return i_ != other.i_; } - - iterator_type i_; -}; - -/** STL-style list interface for sigc::signal#. - * slot_list can be used to iterate over the list of slots that - * is managed by a signal. Slots can be added or removed from - * the list while existing iterators stay valid. A slot_list - * object can be retrieved from the signal's slots() function. - * - * @ingroup signal - */ -template -struct slot_list -{ - typedef T_slot slot_type; - - typedef slot_type& reference; - typedef const slot_type& const_reference; - - typedef slot_iterator iterator; - typedef slot_const_iterator const_iterator; - - #ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - #else - typedef std::reverse_iterator reverse_iterator; - - typedef std::reverse_iterator const_reverse_iterator; - #endif /* SIGC_HAVE_SUN_REVERSE_ITERATOR */ - - - slot_list() - : list_(nullptr) {} - - explicit slot_list(internal::signal_impl* __list) - : list_(__list) {} - - iterator begin() - { return iterator(list_->slots_.begin()); } - - const_iterator begin() const - { return const_iterator(list_->slots_.begin()); } - - iterator end() - { return iterator(list_->slots_.end()); } - - const_iterator end() const - { return const_iterator(list_->slots_.end()); } - - reverse_iterator rbegin() - { return reverse_iterator(end()); } - - const_reverse_iterator rbegin() const - { return const_reverse_iterator(end()); } - - reverse_iterator rend() - { return reverse_iterator(begin()); } - - const_reverse_iterator rend() const - { return const_reverse_iterator(begin()); } - - reference front() - { return *begin(); } - - const_reference front() const - { return *begin(); } - - reference back() - { return *(--end()); } - - const_reference back() const - { return *(--end()); } - - iterator insert(iterator i, const slot_type& slot_) - { return iterator(list_->insert(i.i_, static_cast(slot_))); } - - iterator insert(iterator i, slot_type&& slot_) - { return iterator(list_->insert(i.i_, std::move(static_cast(slot_)))); } - - void push_front(const slot_type& c) - { insert(begin(), c); } - - void push_front(slot_type&& c) - { insert(begin(), std::move(c)); } - - void push_back(const slot_type& c) - { insert(end(), c); } - - void push_back(slot_type&& c) - { insert(end(), std::move(c)); } - - iterator erase(iterator i) - { return iterator(list_->erase(i.i_)); } - - iterator erase(iterator first_, iterator last_) - { - while (first_ != last_) - first_ = erase(first_); - return last_; - } - - void pop_front() - { erase(begin()); } - - void pop_back() - { - auto tmp_ = end(); - erase(--tmp_); - } - -protected: - internal::signal_impl* list_; -}; - - -namespace internal { - -/** Special iterator over sigc::internal::signal_impl's slot list that holds extra data. - * This iterators is for use in accumulators. operator*() executes - * the slot. The return value is buffered, so that in an expression - * like @code a = (*i) * (*i); @endcode the slot is executed only once. - */ -template -struct slot_iterator_buf -{ - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - //These are needed just to make this a proper C++ iterator, - //that can be used with standard C++ algorithms. - typedef T_result value_type; - typedef T_result& reference; - typedef T_result* pointer; - - typedef T_emitter emitter_type; - typedef T_result result_type; - typedef typename T_emitter::slot_type slot_type; - - typedef signal_impl::const_iterator_type iterator_type; - - slot_iterator_buf() - : c_(nullptr), invoked_(false) {} - - slot_iterator_buf(const iterator_type& i, const emitter_type* c) - : i_(i), c_(c), invoked_(false) {} - - result_type operator*() const - { - if (!i_->empty() && !i_->blocked() && !invoked_) - { - r_ = (*c_)(static_cast(*i_)); - invoked_ = true; - } - return r_; - } - - slot_iterator_buf& operator++() - { - ++i_; - invoked_ = false; - return *this; - } - - slot_iterator_buf operator++(int) - { - slot_iterator_buf __tmp(*this); - ++i_; - invoked_ = false; - return __tmp; - } - - slot_iterator_buf& operator--() - { - --i_; - invoked_ = false; - return *this; - } - - slot_iterator_buf operator--(int) - { - slot_iterator_buf __tmp(*this); - --i_; - invoked_ = false; - return __tmp; - } - - bool operator == (const slot_iterator_buf& other) const - { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty. - * Unfortunately, empty stl iterators are not equal. - * We are forcing equality so that 'first==last' - * in the accumulator's emit function yields true. */ - - bool operator != (const slot_iterator_buf& other) const - { return (c_ && (i_ != other.i_)); } - -private: - iterator_type i_; - const emitter_type* c_; - mutable result_type r_; - mutable bool invoked_; -}; - -/** Template specialization of slot_iterator_buf for void return signals. - */ -template -struct slot_iterator_buf -{ - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - typedef T_emitter emitter_type; - typedef void result_type; - typedef typename T_emitter::slot_type slot_type; - - typedef signal_impl::const_iterator_type iterator_type; - - slot_iterator_buf() - : c_(nullptr), invoked_(false) {} - - slot_iterator_buf(const iterator_type& i, const emitter_type* c) - : i_(i), c_(c), invoked_(false) {} - - void operator*() const - { - if (!i_->empty() && !i_->blocked() && !invoked_) - { - (*c_)(static_cast(*i_)); - invoked_ = true; - } - } - - slot_iterator_buf& operator++() - { - ++i_; - invoked_ = false; - return *this; - } - - slot_iterator_buf operator++(int) - { - slot_iterator_buf __tmp(*this); - ++i_; - invoked_ = false; - return __tmp; - } - - slot_iterator_buf& operator--() - { - --i_; - invoked_ = false; - return *this; - } - - slot_iterator_buf operator--(int) - { - slot_iterator_buf __tmp(*this); - --i_; - invoked_ = false; - return __tmp; - } - - bool operator == (const slot_iterator_buf& other) const - { return i_ == other.i_; } - - bool operator != (const slot_iterator_buf& other) const - { return i_ != other.i_; } - -private: - iterator_type i_; - const emitter_type* c_; - mutable bool invoked_; -}; - -/** Reverse version of sigc::internal::slot_iterator_buf. */ -template -struct slot_reverse_iterator_buf -{ - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - //These are needed just to make this a proper C++ iterator, - //that can be used with standard C++ algorithms. - typedef T_result value_type; - typedef T_result& reference; - typedef T_result* pointer; - - typedef T_emitter emitter_type; - typedef T_result result_type; - typedef typename T_emitter::slot_type slot_type; - - typedef signal_impl::const_iterator_type iterator_type; - - slot_reverse_iterator_buf() - : c_(nullptr), invoked_(false) {} - - slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c) - : i_(i), c_(c), invoked_(false) {} - - result_type operator*() const - { - iterator_type __tmp(i_); - --__tmp; - if (!__tmp->empty() && !__tmp->blocked() && !invoked_) - { - r_ = (*c_)(static_cast(*__tmp)); - invoked_ = true; - } - return r_; - } - - slot_reverse_iterator_buf& operator++() - { - --i_; - invoked_ = false; - return *this; - } - - slot_reverse_iterator_buf operator++(int) - { - slot_reverse_iterator_buf __tmp(*this); - --i_; - invoked_ = false; - return __tmp; - } - - slot_reverse_iterator_buf& operator--() - { - ++i_; - invoked_ = false; - return *this; - } - - slot_reverse_iterator_buf operator--(int) - { - slot_reverse_iterator_buf __tmp(*this); - ++i_; - invoked_ = false; - return __tmp; - } - - bool operator == (const slot_reverse_iterator_buf& other) const - { return (!c_ || (i_ == other.i_)); } /* If '!c_' the iterators are empty. - * Unfortunately, empty stl iterators are not equal. - * We are forcing equality so that 'first==last' - * in the accumulator's emit function yields true. */ - - bool operator != (const slot_reverse_iterator_buf& other) const - { return (c_ && (i_ != other.i_)); } - -private: - iterator_type i_; - const emitter_type* c_; - mutable result_type r_; - mutable bool invoked_; -}; - -/** Template specialization of slot_reverse_iterator_buf for void return signals. - */ -template -struct slot_reverse_iterator_buf -{ - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - - typedef T_emitter emitter_type; - typedef void result_type; - typedef typename T_emitter::slot_type slot_type; - - typedef signal_impl::const_iterator_type iterator_type; - - slot_reverse_iterator_buf() - : c_(nullptr), invoked_(false) {} - - slot_reverse_iterator_buf(const iterator_type& i, const emitter_type* c) - : i_(i), c_(c), invoked_(false) {} - - void operator*() const - { - iterator_type __tmp(i_); - --__tmp; - if (!__tmp->empty() && !__tmp->blocked() && !invoked_) - { - (*c_)(static_cast(*__tmp)); - invoked_ = true; - } - } - - slot_reverse_iterator_buf& operator++() - { - --i_; - invoked_ = false; - return *this; - } - - slot_reverse_iterator_buf operator++(int) - { - slot_reverse_iterator_buf __tmp(*this); - --i_; - invoked_ = false; - return __tmp; - } - - slot_reverse_iterator_buf& operator--() - { - ++i_; - invoked_ = false; - return *this; - } - - slot_reverse_iterator_buf operator--(int) - { - slot_reverse_iterator_buf __tmp(*this); - ++i_; - invoked_ = false; - return __tmp; - } - - bool operator == (const slot_reverse_iterator_buf& other) const - { return i_ == other.i_; } - - bool operator != (const slot_reverse_iterator_buf& other) const - { return i_ != other.i_; } - -private: - iterator_type i_; - const emitter_type* c_; - mutable bool invoked_; -}; - -FOR(0,CALL_SIZE,[[SIGNAL_EMIT_N(%1)]]) -} /* namespace internal */ - -FOR(0,CALL_SIZE,[[SIGNAL_N(%1)]]) - -SIGNAL(CALL_SIZE,CALL_SIZE) -FOR(0,eval(CALL_SIZE-1),[[SIGNAL(%1)]]) - -} /* namespace sigc */ - -#ifdef SIGC_NIL_HAS_BEEN_PUSHED - #undef SIGC_NIL_HAS_BEEN_PUSHED - #pragma pop_macro("nil") -#endif - -#endif /* _SIGC_SIGNAL_H_ */ diff --git a/sigc++/macros/template.macros.m4 b/sigc++/macros/template.macros.m4 deleted file mode 100644 index 8a41bcc5..00000000 --- a/sigc++/macros/template.macros.m4 +++ /dev/null @@ -1,86 +0,0 @@ -dnl Copyright 2002, The libsigc++ Development Team -dnl -dnl This library is free software; you can redistribute it and/or -dnl modify it under the terms of the GNU Lesser General Public -dnl License as published by the Free Software Foundation; either -dnl version 2.1 of the License, or (at your option) any later version. -dnl -dnl This library is distributed in the hope that it will be useful, -dnl but WITHOUT ANY WARRANTY; without even the implied warranty of -dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -dnl Lesser General Public License for more details. -dnl -dnl You should have received a copy of the GNU Lesser General Public -dnl License along with this library; if not, write to the Free Software -dnl Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -dnl -define(__t_div__,divnum)divert(-1) -dnl -dnl M4 macros for building large files quickly -dnl -divert(0)// -*- c++ -*- -/* Do not edit! -- generated file */ -divert(-1) -changequote([, ]) -changecom() - -dnl -dnl Macros for sigc specifically. -dnl - -define([CALL_SIZE],7) - -#Generate header guards: -define([_FIREWALL],[dnl -#ifndef _SIGC_$1_H_ -#define _SIGC_$1_H_[]dnl -divert(1)dnl -#endif /* _SIGC_$1_H_ */ -divert(0)dnl -]) - -define([_R_],[type_trait_take_t<$1>]) -define([_P_],[type_trait_pass_t<$1>]) - -define([__DEPRECATION_GUARD__],[SIGCXX_DISABLE_DEPRECATED])dnl -dnl Start deprecation -define([_DEPRECATE_IFDEF_START],[dnl -#ifndef __DEPRECATION_GUARD__])dnl -dnl End deprecation -define([_DEPRECATE_IFDEF_END],[dnl -#endif // __DEPRECATION_GUARD__])dnl - -dnl -dnl General macros -dnl - -define([PROT],[[$*]]) - -define([_LOOP], -[ifelse(eval($1<$2),0, -[indir([_LOOP_FORMAT], $1)], -[indir([_LOOP_FORMAT], $1)[]_LOOP_SEP[]_LOOP(eval($1+1), $2)])]) - -define([LOOP], -[pushdef([_LOOP_FORMAT], translit([$1],%, $))dnl -pushdef([_LOOP_SEP],ifelse([$3],[],[[[, ]]],[$3]))dnl -ifelse(eval($2>0),1,[PROT(_LOOP(1, $2))],[PROT()])dnl -popdef([_LOOP_SEP])dnl -popdef([_LOOP_FORMAT])dnl -]) - -define([NUM],[eval(ifelse([$1],,0,1)ifelse($#,0,0, $#,1,,[+NUM(shift($@))]))]) -define([LIST],[ifelse($#,0,, $#,1,[$1],[$1],,[LIST(shift($@))],[__LIST($@)])]) -define([__LIST],[ifelse($#,0,, $#,1,[$1],[$1[]ifelse([$2],,,[[, ]])__LIST(shift($@))])]) -dnl -define([_NL_],[ -]) - -define([FOR], -[pushdef([_FOR_FUNC],PROT(translit([$3],%, $)))dnl -_FOR($1, $2)[]dnl -popdef([_FOR_FUNC])dnl -]) -define([_FOR],[ifelse(eval($1>$2),1,[],[_FOR_FUNC($1)[]_FOR(eval($1+1), $2)])]) - -divert(__t_div__)dnl diff --git a/sigc++/member_method_trait.h b/sigc++/member_method_trait.h new file mode 100644 index 00000000..9d9b2a07 --- /dev/null +++ b/sigc++/member_method_trait.h @@ -0,0 +1,147 @@ +/* Copyright 2002 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ +#ifndef SIGC_MEMBER_METHOD_TRAITS_H +#define SIGC_MEMBER_METHOD_TRAITS_H + +#include + +namespace sigc +{ + +namespace internal +{ + +template +struct member_method_is_const; + +template +struct member_method_is_const +{ + constexpr static bool value = false; +}; + +template +struct member_method_is_const +{ + constexpr static bool value = false; +}; + +template +struct member_method_is_const +{ + constexpr static bool value = true; +}; + +template +struct member_method_is_const +{ + constexpr static bool value = true; +}; + +template +struct member_method_is_volatile; + +template +struct member_method_is_volatile +{ + constexpr static bool value = false; +}; + +template +struct member_method_is_volatile +{ + constexpr static bool value = false; +}; + +template +struct member_method_is_volatile +{ + constexpr static bool value = true; +}; + +template +struct member_method_is_volatile +{ + constexpr static bool value = true; +}; + +// member method class: + +template +struct member_method_class +{ +}; + +template +struct member_method_class +{ + using type = T_obj; +}; + +template +struct member_method_class +{ + using type = T_obj; +}; + +template +struct member_method_class +{ + using type = T_obj; +}; + +template +struct member_method_class +{ + using type = T_obj; +}; + +// member method result: + +template +struct member_method_result +{ +}; + +template +struct member_method_result +{ + using type = T_result; +}; + +template +struct member_method_result +{ + using type = T_result; +}; + +template +struct member_method_result +{ + using type = T_result; +}; + +template +struct member_method_result +{ + using type = T_result; +}; + +} // namespace internal + +} // namespace sigc + +#endif /* SIGC_MEMBER_METHOD_TRAITS_H */ diff --git a/sigc++/meson.build b/sigc++/meson.build new file mode 100644 index 00000000..4f62bad0 --- /dev/null +++ b/sigc++/meson.build @@ -0,0 +1,142 @@ +# sigc++ + +# Input: sigcxx_build_dep, sigcxx_pcname, sigcxx_libversion, sigcxx_api_version, +# darwin_versions, install_includedir, sig_rc, msvc_static_cxxflag, +# is_msvc_style +# Output: source_h_files, sigcxx_own_dep + +# There are no built source files in libsigc++-3.0. + +source_cc_files = [ + 'connection.cc', + 'scoped_connection.cc', + 'signal_base.cc', + 'trackable.cc', + 'functors' / 'slot_base.cc', +] + +sigc_h_files = [ + 'bind.h', + 'bind_return.h', + 'connection.h', + 'limit_reference.h', + 'member_method_trait.h', + 'reference_wrapper.h', + 'retype_return.h', + 'scoped_connection.h', + 'signal.h', + 'signal_base.h', + 'signal_connect.h', + 'slot.h', + 'trackable.h', + 'type_traits.h', + 'visit_each.h', + 'weak_raw_ptr.h', +] +adaptors_h_files = [ + 'adaptors' / 'adaptor_base.h', + 'adaptors' / 'adaptors.h', + 'adaptors' / 'adaptor_trait.h', + 'adaptors' / 'adapts.h', + 'adaptors' / 'bind.h', + 'adaptors' / 'bind_return.h', + 'adaptors' / 'bound_argument.h', + 'adaptors' / 'compose.h', + 'adaptors' / 'exception_catch.h', + 'adaptors' / 'hide.h', + 'adaptors' / 'retype.h', + 'adaptors' / 'retype_return.h', + 'adaptors' / 'track_obj.h', + 'adaptors' / 'tuple_visitor_visit_each.h', +] +functors_h_files = [ + 'functors' / 'functor_trait.h', + 'functors' / 'functors.h', + 'functors' / 'mem_fun.h', + 'functors' / 'ptr_fun.h', + 'functors' / 'slot.h', + 'functors' / 'slot_base.h', +] +tuple_utils_h_files = [ + 'tuple-utils' / 'tuple_cdr.h', + 'tuple-utils' / 'tuple_end.h', + 'tuple-utils' / 'tuple_for_each.h', + 'tuple-utils' / 'tuple_start.h', + 'tuple-utils' / 'tuple_transform_each.h', +] + +source_h_files = sigc_h_files + adaptors_h_files + functors_h_files + tuple_utils_h_files + +install_headers('sigc++.h', subdir: sigcxx_pcname / 'sigc++') +install_headers(sigc_h_files, subdir: sigcxx_pcname / 'sigc++') +install_headers(adaptors_h_files, subdir: sigcxx_pcname / 'sigc++' / 'adaptors') +install_headers(functors_h_files, subdir: sigcxx_pcname / 'sigc++' / 'functors') +install_headers(tuple_utils_h_files, subdir: sigcxx_pcname / 'sigc++' / 'tuple-utils') + +extra_sigc_cppflags = [] +extra_sigc_objects = [] + +# Make sure we are exporting the symbols from the DLL +if is_msvc_style + extra_sigc_cppflags += ['-DSIGC_BUILD'] +endif + +# Build the .rc file for Windows builds and link to it +if host_machine.system() == 'windows' + windows = import('windows') + if get_option('default_library') == 'shared' + sigc_res = windows.compile_resources(sigc_rc) + extra_sigc_objects += sigc_res + endif +endif + +extra_include_dirs = ['..'] +sigcxx_library = library('sigc-' + sigcxx_api_version, + source_cc_files, + extra_sigc_objects, + version: sigcxx_libversion, + darwin_versions: darwin_versions, + implicit_include_directories: false, + include_directories: extra_include_dirs, + cpp_args: extra_sigc_cppflags, + dependencies: sigcxx_build_dep, + install: true, +) + +# Generate .pc files, used by pkg-config. +pkg_config = import('pkgconfig') +pc_common_variables = [ + 'doxytagfile=${docdir}/reference/lib' + sigcxx_pcname + '.tag', + 'htmlrefdir=${docdir}/reference/html', + 'htmlrefpub=https://libsigcplusplus.github.io/libsigcplusplus/reference/html', +] +pc_variables = [ + 'exec_prefix=${prefix}', + 'datarootdir=${datadir}', + 'docdir=${datadir}/doc/lib' + sigcxx_pcname, +] + pc_common_variables +pc_uninstalled_variables = [ + 'docdir=${prefix}/docs/docs', +] + pc_common_variables + +pkg_config.generate(sigcxx_library, + filebase: sigcxx_pcname, + variables: pc_variables, + uninstalled_variables: pc_uninstalled_variables, + name: meson.project_name(), + description: 'Typesafe signal and callback system for C++', + url: 'https://libsigcplusplus.github.io/libsigcplusplus/', + subdirs: [sigcxx_pcname], + extra_cflags: [ + '-I${libdir}/' + sigcxx_pcname + '/include', + msvc_static_cxxflag, + ], +) + +# This is used when building example programs and test programs. +# It's also a part of sigcxx_dep, when libsigc++ is a subproject. +sigcxx_own_dep = declare_dependency( + link_with: sigcxx_library, + include_directories: extra_include_dirs, + dependencies: sigcxx_build_dep +) diff --git a/sigc++/reference_wrapper.h b/sigc++/reference_wrapper.h index 5a57e916..df256a6f 100644 --- a/sigc++/reference_wrapper.h +++ b/sigc++/reference_wrapper.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,99 +11,48 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_REFERENCE_WRAPPER_H_ -#define _SIGC_REFERENCE_WRAPPER_H_ - -namespace sigc { - -/** Reference wrapper. - * Use sigc::ref() to create a reference wrapper. - */ -template -struct reference_wrapper -{ - explicit reference_wrapper(T_type& v) - : value_(v) {} +#ifndef SIGC_REFERENCE_WRAPPER_H +#define SIGC_REFERENCE_WRAPPER_H - operator T_type& () const - { return value_; } +#include - T_type& value_; -}; - -/** Const reference wrapper. - * Use sigc::ref() to create a const reference wrapper. - */ -template -struct const_reference_wrapper +namespace sigc { - explicit const_reference_wrapper(const T_type& v) - : value_(v) {} - operator const T_type& () const - { return value_; } - - const T_type& value_; -}; - -/** Creates a reference wrapper. - * Passing an object throught sigc::ref() makes libsigc++ adaptors - * like, e.g., sigc::bind store references to the object instead of copies. - * If the object type inherits from sigc::trackable this will ensure - * automatic invalidation of the adaptors when the object is deleted - * or overwritten. - * - * @param v Reference to store. - * @return A reference wrapper. - */ -template -reference_wrapper ref(T_type& v) -{ return reference_wrapper(v); } - -/** Creates a const reference wrapper. - * Passing an object throught sigc::ref() makes libsigc++ adaptors - * like, e.g., sigc::bind store references to the object instead of copies. - * If the object type inherits from sigc::trackable this will ensure - * automatic invalidation of the adaptors when the object is deleted - * or overwritten. - * - * @param v Reference to store. - * @return A reference wrapper. - */ -template -const_reference_wrapper ref(const T_type& v) -{ return const_reference_wrapper(v); } - -template +template struct unwrap_reference { - typedef T_type type; + using type = T_type; }; -template -struct unwrap_reference > +template +struct unwrap_reference> { - typedef T_type& type; + using type = T_type&; }; -template -struct unwrap_reference > +template +struct unwrap_reference> { - typedef const T_type& type; + using type = const T_type&; }; -template -T_type& unwrap(const reference_wrapper& v) -{ return v; } +template +T_type& +unwrap(const std::reference_wrapper& v) +{ + return v; +} -template -const T_type& unwrap(const const_reference_wrapper& v) -{ return v; } +template +const T_type& +unwrap(const std::reference_wrapper& v) +{ + return v; +} } /* namespace sigc */ -#endif /* _SIGC_REFERENCE_WRAPPER_H_ */ +#endif /* SIGC_REFERENCE_WRAPPER_H */ diff --git a/sigc++/retype_return.h b/sigc++/retype_return.h index c1d08d7e..8264c713 100644 --- a/sigc++/retype_return.h +++ b/sigc++/retype_return.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,14 +11,11 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_RETYPE_RETURN_HPP_ -#define _SIGC_RETYPE_RETURN_HPP_ +#ifndef SIGC_RETYPE_RETURN_HPP +#define SIGC_RETYPE_RETURN_HPP #include - -#endif /* _SIGC_RETYPE_RETURN_HPP_ */ +#endif /* SIGC_RETYPE_RETURN_HPP */ diff --git a/sigc++/scoped_connection.cc b/sigc++/scoped_connection.cc new file mode 100644 index 00000000..1eae69f0 --- /dev/null +++ b/sigc++/scoped_connection.cc @@ -0,0 +1,114 @@ +/* Copyright 2023, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include +#include + +namespace sigc +{ + +// All we are doing is assigning weak_raw_ptr, which is noexcept, so declare it. +// connectionʼs copy operators can be noexcept for that reason, if breaking ABI. +scoped_connection::scoped_connection(connection c) noexcept +: conn_(std::move(c)) +{ +} + +scoped_connection& +scoped_connection::operator=(connection c) +{ + conn_.disconnect(); + conn_ = std::move(c); + return *this; +} + +// We do not implement move-ctor in terms of move-assign, so we can be noexcept, +// as we do not need to call the maybe-throwing disconnect() for obvious reason. +scoped_connection::scoped_connection(scoped_connection&& sc) noexcept +: conn_(std::exchange(sc.conn_, connection())) +{ +} + +scoped_connection& +scoped_connection::operator=(scoped_connection&& sc) +{ + conn_.disconnect(); + conn_ = std::exchange(sc.conn_, connection()); + return *this; +} + +scoped_connection::~scoped_connection() +{ + conn_.disconnect(); +} + +bool +scoped_connection::empty() const noexcept +{ + return conn_.empty(); +} + +bool +scoped_connection::connected() const noexcept +{ + return conn_.connected(); +} + +bool +scoped_connection::blocked() const noexcept +{ + return conn_.blocked(); +} + +bool +scoped_connection::block(bool should_block) noexcept +{ + return conn_.block(should_block); +} + +bool +scoped_connection::unblock() noexcept +{ + return conn_.unblock(); +} + +void +scoped_connection::disconnect() +{ + conn_.disconnect(); +} + +scoped_connection::operator bool() const noexcept +{ + return conn_.operator bool(); +} + +// Swapping can be noexcept, as it does not need to disconnect either connection +// because they will still stay alive, just in opposite instances post-swapping. +void +swap(scoped_connection& sca, scoped_connection& scb) noexcept +{ + using std::swap; + swap(sca.conn_, scb.conn_); +} + +connection +scoped_connection::release() noexcept +{ + return std::exchange(conn_, connection()); +} + +} /* namespace sigc */ diff --git a/sigc++/scoped_connection.h b/sigc++/scoped_connection.h new file mode 100644 index 00000000..3b297f91 --- /dev/null +++ b/sigc++/scoped_connection.h @@ -0,0 +1,175 @@ +/* Copyright 2023, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_SCOPED_CONNECTION_HPP +#define SIGC_SCOPED_CONNECTION_HPP + +#include + +namespace sigc +{ + +/** Convenience class for safe disconnection, including automatic disconnection + * upon destruction. + * + * This is a variant of @ref sigc::connection which also disconnect()s the slot + * automatically when the scoped_connection is destructed or re-assigned. Refer + * to @ref sigc::connection for full information about the common functionality. + * + * You will use sigc::scoped_connection by constructing it from a ‘normal’, + * unscoped @ref sigc::connection, such as those returned by + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" and + * @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()", + * thus ‘wrapping’ the connection in a scoped_connection, adding auto-disconnection. + * It can also be assigned from an unscoped connection, in which case, if there + * was a previous slot referred to by the scoped connection, it is disconnected. + * + * Once a connection is scoped, it canʼt be copied as that would make it unclear + * which of the copies would hold responsibility to auto-disconnect the slot. It + * can, however, be moved, so itʼs usable in containers or so ‘ownership’ of the + * connection/auto-disconnect can be moved to another instance. Moving from the + * scoped_connection clears its reference to the slot so it wonʼt disconnect it. + * + * If you want a reference-counted scoped_connection, wrap in a std::shared_ptr. + * + * @code + * // Automatic disconnection: + * { + * sigc::scoped_connection sconn = sig.connect(&some_function); + * // Do stuff that requires the slot to be connected & called. + * } + * // The scoped_connection was destroyed, so the slot is no longer connected. + * + * // *** + * + * // Moving ownership: + * { + * sigc::scoped_connection sconn = sig.connect(&some_function); + * // Do stuff that requires the slot to be connected & called. + * take_ownership(std::move(sconn)); // Pass by rvalue. + * } + * // Now our `sconn` no longer referred to slot, so it did NOT auto-disconnect. + * + * // *** + * + * // Shared ownership: + * { + * auto shconn = std::make_shared(sig.connect(&some_function)); + * take_copy(shconn); // Pass by copy/value + * // Now we AND take_copy() must destroy our shared_ptr to auto-disconnect(). + * } + * // take_copy() may still hold a shared_ptr reference, keeping the slot alive. + * @endcode + * + * @ingroup signal + * @newin{3,6} + */ +struct SIGC_API scoped_connection final +{ + /** Constructs an empty scoped connection object. */ + scoped_connection() noexcept = default; + + /** Constructs a scoped connection object from an unscoped connection object. + * The source connection still refers to the slot and can manually disconnect. + * @param c The connection object to make a copy from, whose slot weʼll + * automatically disconnect when the scoped_connection object is destroyed. + */ + scoped_connection(connection c) noexcept; + + /** Overrides this scoped connection object copying an unscoped connection. + * The current slot, if any, will be disconnect()ed before being replaced. + * The source connection still refers to the slot and can manually disconnect. + * @param c The connection object to make a copy from, whose slot weʼll + * automatically disconnect when the scoped_connection object is destroyed. + */ + scoped_connection& operator=(connection c); + + /// scoped_connection canʼt be copied as it would confuse ownership—see intro. + scoped_connection& operator=(const scoped_connection&) = delete; + /// scoped_connection canʼt be copied as it would confuse ownership—see intro. + scoped_connection(const scoped_connection&) = delete; + + /** Constructs a scoped connection object moving an existing one. + * The source scoped connection will no longer refer to / disconnect the slot. + * @param sc The scoped connection object to move from. + */ + scoped_connection(scoped_connection&& sc) noexcept; + + /** Overrides this scoped connection object moving another one. + * The current slot, if any, will be disconnect()ed before being replaced. + * The source scoped connection will no longer refer to / disconnect the slot. + * @param sc The scoped connection object to move from. + */ + scoped_connection& operator=(scoped_connection&& sc); + + /// Swap two scoped connections. + friend SIGC_API void swap(scoped_connection& sca, scoped_connection& scb) noexcept; + + /// scoped_connection disconnects the referred slot, if any, upon destruction. + ~scoped_connection(); + + /** Returns whether the connection is still active. + * @return @p false if the connection is still active. + */ + bool empty() const noexcept; + + /** Returns whether the connection is still active. + * @return @p true if the connection is still active. + */ + bool connected() const noexcept; + + /** Returns whether the connection is blocked. + * @return @p true if the connection is blocked. + */ + bool blocked() const noexcept; + + /** Sets or unsets the blocking state of this connection. + * See slot_base::block() for details. + * @param should_block Indicates whether the blocking state should be set or unset. + * @return @p true if the connection has been in blocking state before. + */ + bool block(bool should_block = true) noexcept; + + /** Unsets the blocking state of this connection. + * @return @p true if the connection has been in blocking state before. + */ + bool unblock() noexcept; + + /// Disconnects the referred slot. This will also happen upon destruction. + void disconnect(); + + /** Returns whether the connection is still active. + * @return @p true if the connection is still active. + */ + explicit operator bool() const noexcept; + + /** Releases the connection from a scoped connection object. + * The scoped connection will no longer refer to / disconnect the slot. + * @return An unscoped connection object referring to the same slot. + */ + connection release() noexcept; + +private: + sigc::connection conn_; +}; + +/// Swap two scoped connections. +SIGC_API +void swap(scoped_connection& sca, scoped_connection& scb) noexcept; + +} /* namespace sigc */ + +#endif /* SIGC_SCOPED_CONNECTION_HPP */ diff --git a/sigc++/sigc++.h b/sigc++/sigc++.h index 24d34242..0bef5489 100644 --- a/sigc++/sigc++.h +++ b/sigc++/sigc++.h @@ -1,5 +1,4 @@ -/* - * Copyright 2003, The libsigc++ Development Team +/* Copyright 2003 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,9 +11,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ #ifndef SIGCXX_SIGCXX_H @@ -24,24 +21,25 @@ * * @section description Description * - * libsigc++ provides a typesafe (at compile time) callback system for standard - * C++. It allows you to define signals and to connect those signals to any - * callback function, either a global or a member function, regardless of whether - * it is static or virtual. It also contains adaptor classes for connection of + * libsigc++ provides a typesafe (at compile time) callback system for standard + * C++. It allows you to define signals and to connect those signals to any + * callback function, either a global or a member function, regardless of whether + * it is static or virtual. It also contains adaptor classes for connection of * dissimilar callbacks. * - * For instance, see the @ref signal "Signals", @ref sigcfunctors "Functors", + * For instance, see the @ref signal "Signals", @ref sigcfunctors "Functors", * @ref slot "Slots" and @ref adaptors "Adaptors". * - * See also the - * libsigc++ tutorial, - * the libsigc++ website, and - * the Signals appendix of the Programming with gtkmm book. + * See also the + * libsigc++ tutorial, + * the libsigc++ website, and + * the + * Signals appendix of the Programming with gtkmm book. * * @section features Features * * - Compile-time typesafe callbacks (also faster than run time checks) - * - Type-safety violations report the line number correctly with template names + * - Type-safety violations report the line number correctly with template names * (no tracing template failures into headers) * - No compiler extensions or meta compilers required * - Proper handling of dynamic objects and signals (deleted objects will not @@ -62,30 +60,63 @@ * * If your source file is @c program.cc, you can compile it with: * @code - * g++ program.cc -o program `pkg-config --cflags --libs sigc++-2.0` + * g++ program.cc -o program `pkg-config --cflags --libs sigc++-3.0` + * @endcode + * If your version of g++ is not C++17-compliant by default, + * add the @c -std=c++17 option. + * + * @subsection meson Using Meson + * + * If using Meson, include the following + * in @c meson.build: + * @code + * sigc_dep = dependency('sigc++-3.0') + * program_name = 'program' + * cpp_sources = [ 'program.cc' ] + * executable(program_name, + * cpp_sources, + * dependencies: sigc_dep + * ) * @endcode * + * Your @c dependencies: keyword argument should also mention any other libraries + * that you need to use. + * + * @subsection autotools Using Autotools + * * Alternatively, if using autoconf, use the following in @c configure.ac: * @code - * PKG_CHECK_MODULES([LIBSIGC], [sigc++-2.0]) + * PKG_CHECK_MODULES([DEPS], [sigc++-3.0]) * @endcode - * Then use the generated @c LIBSIGC_CFLAGS and @c LIBSIGC_LIBS variables + * Then use the generated @c DEPS_CFLAGS and @c DEPS_LIBS variables * in the project @c Makefile.am files. For example: * @code - * program_CPPFLAGS = $(LIBSIGC_CFLAGS) - * program_LDADD = $(LIBSIGC_LIBS) + * yourprogram_CPPFLAGS = $(DEPS_CFLAGS) + * yourprogram_LDADD = $(DEPS_LIBS) * @endcode * - * @section scope Scope of Documentation + * Your @c PKG_CHECK_MODULES() call should also mention any other libraries that + * you need to use via pkg-config. + * + * @subsection cmake Using CMake + * + * If using CMake, use the following in @c CMakeList.txt: + * @code + * include(FindPkgConfig) + * pkg_check_modules(DEPS REQUIRED sigc++-3.0) + * include_directories(${DEPS_INCLUDE_DIRS}) + * target_link_libraries(yourprogram ${DEPS_LIBRARIES}) + * @endcode * - * libsigc++ contains many template functions and template classes/structs, - * some with many specializations. This reference manual does not show all - * specializations of those templates that hardly any user will use directly. + * Your @c pkg_check_modules() call should also mention any other libraries that + * you need to use via pkg-config. */ #include #include +#include #include +#include #include #include diff --git a/sigc++/signal.cc b/sigc++/signal.cc deleted file mode 100644 index 993eee4a..00000000 --- a/sigc++/signal.cc +++ /dev/null @@ -1,25 +0,0 @@ -// -*- c++ -*- -/* - * Copyright 2002, The libsigc++ Development Team - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * - */ -#include - -namespace sigc { - - -} /* sigc */ diff --git a/sigc++/signal.h b/sigc++/signal.h new file mode 100644 index 00000000..d521abc9 --- /dev/null +++ b/sigc++/signal.h @@ -0,0 +1,987 @@ +/* Copyright 2002 - 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_SIGNAL_H +#define SIGC_SIGNAL_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace sigc +{ + +namespace internal +{ + +/** Special iterator over sigc::internal::signal_impl's slot list that holds extra data. + * This iterators is for use in accumulators. operator*() executes + * the slot. The return value is buffered, so that in an expression + * like @code a = (*i) * (*i); @endcode the slot is executed only once. + */ +template +struct slot_iterator_buf +{ + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using iterator_category = std::bidirectional_iterator_tag; + + // These are needed just to make this a proper C++ iterator, + // that can be used with standard C++ algorithms. + using value_type = T_result; + using reference = T_result&; + using pointer = T_result*; + + using emitter_type = T_emitter; + using slot_type = typename T_emitter::slot_type; + + using iterator_type = signal_impl::const_iterator_type; + + slot_iterator_buf() : c_(nullptr), invoked_(false) {} + + slot_iterator_buf(const iterator_type& i, const emitter_type* c) : i_(i), c_(c), invoked_(false) + { + } + + decltype(auto) operator*() const + { + if (!i_->empty() && !i_->blocked() && !invoked_) + { + r_ = (*c_)(static_cast(*i_)); + invoked_ = true; + } + return r_; + } + + slot_iterator_buf& operator++() + { + ++i_; + invoked_ = false; + return *this; + } + + slot_iterator_buf operator++(int) + { + slot_iterator_buf tmp(*this); + ++i_; + invoked_ = false; + return tmp; + } + + slot_iterator_buf& operator--() + { + --i_; + invoked_ = false; + return *this; + } + + slot_iterator_buf operator--(int) + { + slot_iterator_buf tmp(*this); + --i_; + invoked_ = false; + return tmp; + } + + bool operator==(const slot_iterator_buf& src) const + { + return (!c_ || (i_ == src.i_)); + } /* If '!c_' the iterators are empty. + * Unfortunately, empty stl iterators are not equal. + * We are forcing equality so that 'first==last' + * in the accumulator's emit function yields true. */ + + bool operator!=(const slot_iterator_buf& src) const { return (c_ && (i_ != src.i_)); } + +private: + iterator_type i_; + const emitter_type* c_; + mutable T_result r_; + mutable bool invoked_; +}; + +/** Template specialization of slot_iterator_buf for void return signals. + */ +template +struct slot_iterator_buf +{ + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using iterator_category = std::bidirectional_iterator_tag; + + using emitter_type = T_emitter; + using slot_type = typename T_emitter::slot_type; + + using iterator_type = signal_impl::const_iterator_type; + + slot_iterator_buf() : c_(nullptr), invoked_(false) {} + + slot_iterator_buf(const iterator_type& i, const emitter_type* c) : i_(i), c_(c), invoked_(false) + { + } + + void operator*() const + { + if (!i_->empty() && !i_->blocked() && !invoked_) + { + (*c_)(static_cast(*i_)); + invoked_ = true; + } + } + + slot_iterator_buf& operator++() + { + ++i_; + invoked_ = false; + return *this; + } + + slot_iterator_buf operator++(int) + { + slot_iterator_buf tmp(*this); + ++i_; + invoked_ = false; + return tmp; + } + + slot_iterator_buf& operator--() + { + --i_; + invoked_ = false; + return *this; + } + + slot_iterator_buf operator--(int) + { + slot_iterator_buf tmp(*this); + --i_; + invoked_ = false; + return tmp; + } + + bool operator==(const slot_iterator_buf& src) const { return i_ == src.i_; } + + bool operator!=(const slot_iterator_buf& src) const { return i_ != src.i_; } + +private: + iterator_type i_; + const emitter_type* c_; + mutable bool invoked_; +}; + +/** Temporary slot list used during signal emission. + * Through evolution this class is slightly misnamed. It is now + * an index into the slot_list passed into it. It simply keeps track + * of where the end of this list was at construction, and pretends that's + * the end of your list. This way you may connect during emission without + * inadvertently entering an infinite loop, as well as make other + * modifications to the slot_list at your own risk. + */ +struct temp_slot_list +{ + using slot_list = signal_impl::slot_list; + using iterator = signal_impl::iterator_type; + using const_iterator = signal_impl::const_iterator_type; + + explicit temp_slot_list(slot_list& slots) : slots_(slots) + { + placeholder = slots_.insert(slots_.end(), slot_base()); + } + + ~temp_slot_list() { slots_.erase(placeholder); } + + iterator begin() { return slots_.begin(); } + iterator end() { return placeholder; } + const_iterator begin() const { return slots_.begin(); } + const_iterator end() const { return placeholder; } + +private: + slot_list& slots_; + slot_list::iterator placeholder; +}; + +/** Abstracts signal emission. + * This template implements the emit() function of signal_with_accumulator. + * Template specializations are available to optimize signal + * emission when no accumulator is used, for example when the template + * argument @e T_accumulator is @p void. + */ +template +struct signal_emit +{ + using self_type = signal_emit; + using slot_type = slot; + + /** Instantiates the class. + * The parameters are stored in member variables. operator()() passes + * the values on to some slot. + */ + explicit signal_emit(type_trait_take_t... a) : a_(a...) {} + + /** Invokes a slot using the buffered parameter values. + * @param slot Some slot to invoke. + * @return The slot's return value. + */ + T_return operator()(const slot_type& slot) const { return std::apply(slot, a_); } + + /** Executes a list of slots using an accumulator of type @e T_accumulator. + * The arguments are buffered in a temporary instance of signal_emit. + * @param a Arguments to be passed on to the slots. + * @return The accumulated return values of the slot invocations as processed by the accumulator. + */ + static decltype(auto) emit(const std::shared_ptr& impl, + type_trait_take_t... a) + { + using slot_iterator_buf_type = internal::slot_iterator_buf; + + T_accumulator accumulator; + + if (!impl) + return accumulator(slot_iterator_buf_type(), slot_iterator_buf_type()); + + signal_impl_holder exec(impl); + const temp_slot_list slots(impl->slots_); + + self_type self(a...); + return accumulator( + slot_iterator_buf_type(slots.begin(), &self), slot_iterator_buf_type(slots.end(), &self)); + } + +private: + std::tuple...> a_; +}; + +/** Abstracts signal emission. + * This template specialization implements an optimized emit() + * function for the case that no accumulator is used. + */ +template +struct signal_emit +{ +private: + using slot_type = slot; + using call_type = typename slot_type::call_type; + +public: + /** Executes a list of slots. + * The arguments are passed directly on to the slots. + * The return value of the last slot invoked is returned. + * @param first An iterator pointing to the first slot in the list. + * @param last An iterator pointing to the last slot in the list. + * @param a Arguments to be passed on to the slots. + * @return The return value of the last slot invoked. + */ + static decltype(auto) emit(const std::shared_ptr& impl, + type_trait_take_t... a) + { + if (!impl || impl->slots_.empty()) + return T_return(); + + signal_impl_holder exec(impl); + T_return r_ = T_return(); + + // Use this scope to make sure that "slots" is destroyed before "exec" is destroyed. + // This avoids a leak on MSVC++ - see http://bugzilla.gnome.org/show_bug.cgi?id=306249 + { + const temp_slot_list slots(impl->slots_); + auto it = slots.begin(); + for (; it != slots.end(); ++it) + { + if (!it->empty() && !it->blocked()) + break; + } + + if (it == slots.end()) + { + // note that 'T_return r_();' doesn't work => define 'r_' after this line + // and initialize as follows: + return T_return(); + } + + r_ = (sigc::internal::function_pointer_cast(it->rep_->call_))(it->rep_, a...); + for (++it; it != slots.end(); ++it) + { + if (it->empty() || it->blocked()) + continue; + r_ = (sigc::internal::function_pointer_cast(it->rep_->call_))(it->rep_, a...); + } + } + + return r_; + } +}; + +/** Abstracts signal emission. + * This template specialization implements an optimized emit() + * function for the case that no accumulator is used and the + * return type is @p void. + */ +template +struct signal_emit +{ +private: + using slot_type = slot; + using call_type = typename slot_type::call_type; + +public: + /** Executes a list of slots using an accumulator of type @e T_accumulator. + * The arguments are passed directly on to the slots. + * @param a Arguments to be passed on to the slots. + */ + static decltype(auto) emit(const std::shared_ptr& impl, + type_trait_take_t... a) + { + if (!impl || impl->slots_.empty()) + return; + signal_impl_holder exec(impl); + const temp_slot_list slots(impl->slots_); + + for (const auto& slot : slots) + { + if (slot.empty() || slot.blocked()) + continue; + + (sigc::internal::function_pointer_cast(slot.rep_->call_))( + slot.rep_, std::forward>(a)...); + } + } +}; + +} /* namespace internal */ + +/** Signal declaration. + * %signal_with_accumulator can be used to connect() slots that are invoked + * during subsequent calls to emit(). Any functor or slot + * can be passed into connect() or connect_first(). It is converted into a slot + * implicitly. + * + * If you want to connect one signal to another, use make_slot() + * to retrieve a functor that emits the signal when invoked. + * + * Be careful if you directly pass one signal into the connect() or + * connect_first() method of another: a shallow copy of the signal is made and + * the signal's slots are not disconnected until both the signal + * and its clone are destroyed, which is probably not what you want! + * + * The following template arguments are used: + * - @e T_return The desired return type for the emit() function (may be overridden by the + * accumulator). + * - @e T_arg Argument types used in the definition of emit(). + * - @e T_accumulator The accumulator type used for emission. The default + * @p void means that no accumulator should be used, for example if signal + * emission returns the return value of the last slot invoked. + * + * @ingroup signal + */ +template +class signal_with_accumulator : public signal_base +{ +public: + using slot_type = slot; + + /** Add a slot at the end of the list of slots. + * Any functor or slot may be passed into %connect(). + * It will be converted into a slot implicitly. + * The returned connection may be stored for disconnection + * of the slot at some later point. It stays valid until + * the slot is disconnected from the signal. + * std::function<> and C++11 lambda expressions are functors. + * These are examples of functors that can be connected to a signal. + * + * %std::bind() creates a functor, but this functor typically has an + * %operator()() which is a variadic template. + * Our functor_trait can't deduce the result type + * of such a functor. If you first assign the return value of %std::bind() + * to a std::function, you can connect the std::function to a signal. + * + * @param slot_ The slot to add to the list of slots. + * @return A connection. + */ + connection connect(const slot_type& slot_) + { + auto iter = signal_base::connect(slot_); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot at the end of the list of slots. + * @see connect(const slot_type& slot_). + * + * @newin{2,8} + */ + connection connect(slot_type&& slot_) + { + auto iter = signal_base::connect(std::move(slot_)); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot at the beginning of the list of slots. + * Any functor or slot may be passed into %connect_first(). + * It will be converted into a slot implicitly. + * The returned connection may be stored for disconnection + * of the slot at some later point. It stays valid until + * the slot is disconnected from the signal. + * std::function<> and C++11 lambda expressions are functors. + * These are examples of functors that can be connected to a signal. + * + * %std::bind() creates a functor, but this functor typically has an + * %operator()() which is a variadic template. + * Our functor_trait can't deduce the result type + * of such a functor. If you first assign the return value of %std::bind() + * to a std::function, you can connect the std::function to a signal. + * + * @param slot_ The slot to add to the list of slots. + * @return A connection. + * + * @newin{3,6} + */ + connection connect_first(const slot_type& slot_) + { + auto iter = signal_base::connect_first(slot_); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot at the beginning of the list of slots. + * @see connect_first(const slot_type& slot_). + * + * @newin{3,6} + */ + connection connect_first(slot_type&& slot_) + { + auto iter = signal_base::connect_first(std::move(slot_)); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Triggers the emission of the signal. + * During signal emission all slots that have been connected + * to the signal are invoked unless they are manually set into + * a blocking state. The parameters are passed on to the slots. + * If @e T_accumulated is not @p void, an accumulator of this type + * is used to process the return values of the slot invocations. + * Otherwise, the return value of the last slot invoked is returned. + * @param a Arguments to be passed on to the slots. + * @return The accumulated return values of the slot invocations. + */ + decltype(auto) emit(type_trait_take_t... a) const + { + using emitter_type = internal::signal_emit; + return emitter_type::emit(impl_, std::forward>(a)...); + } + + /** Triggers the emission of the signal (see emit()). */ + decltype(auto) operator()(type_trait_take_t... a) const + { + return emit(std::forward>(a)...); + } + + /** Creates a functor that calls emit() on this signal. + * + * @note %sigc::signal does not derive from sigc::trackable. + * If you connect the returned functor that calls %emit() on signal1, + * to another signal (signal2) and then delete signal1, you must manually + * disconnect signal1 from signal2 before you delete signal1. + * Alternatively, make a slot of a sigc::trackable_signal. + * + * @code + * sigc::mem_fun(mysignal, &sigc::signal_with_accumulator::emit) + * @endcode + * yields the same result. + * @return A functor that calls emit() on this signal. + */ + decltype(auto) make_slot() const + { + // TODO: Instead use std::invoke_result<> on the static emitter_type::emit() + using result_type = + typename internal::member_method_result::type; + return bound_mem_functor...) + const, + type_trait_take_t...>(*this, &signal_with_accumulator::emit); + } + + signal_with_accumulator() = default; + + signal_with_accumulator(const signal_with_accumulator& src) : signal_base(src) {} + + signal_with_accumulator(signal_with_accumulator&& src) : signal_base(std::move(src)) {} + + signal_with_accumulator& operator=(const signal_with_accumulator& src) + { + signal_base::operator=(src); + return *this; + } + + signal_with_accumulator& operator=(signal_with_accumulator&& src) + { + signal_base::operator=(std::move(src)); + return *this; + } +}; + +/** signal can be used to connect() slots that are invoked + * during subsequent calls to emit(). Any functor or slot + * can be passed into connect() or connect_first(). It is converted into a slot + * implicitly. + * + * If you want to connect one signal to another, use make_slot() + * to retrieve a functor that emits the signal when invoked. + * + * Be careful if you directly pass one signal into the connect() or + * connect_first() method of another: a shallow copy of the signal is made and + * the signal's slots are not disconnected until both the signal + * and its clone are destroyed, which is probably not what you want! + * + * The template arguments determine the function signature of + * the emit() function: + * - @e T_return The desired return type of the emit() function. + * - @e T_arg Argument types used in + * the definition of emit(). + * + * For instance, to declare a signal whose connected slot returns void and takes + * two parameters of bool and int: + * @code + * sigc::signal some_signal; + * @endcode + * + * To specify an accumulator type the nested class signal::accumulated can be used. + * + * @par Example: + * @code + * void foo(int) {} + * sigc::signal sig; + * sig.connect(sigc::ptr_fun(&foo)); + * sig.emit(19); + * @endcode + * + * @ingroup signal + */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +class signal final { + static_assert(sizeof...(T_arg) < 0, "The signal syntax has been removed. Use the signal syntax."); +}; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +template +class signal : public signal_with_accumulator +{ +public: + using accumulator_type = void; + + /** Like @ref sigc::signal "sigc::signal" but the additional + * template parameter @e T_accumulator defines the accumulator type that should be used. + * + * An accumulator is a functor that uses a pair of special iterators + * to step through a list of slots and calculate a return value + * from the results of the slot invocations. The iterators' operator*() + * executes the slot. The return value is buffered, so that in an expression + * like @code a = (*i) * (*i); @endcode the slot is executed only once. + * + * @par Example 1: + * This accumulator calculates the arithmetic mean value: + * @code + * struct arithmetic_mean_accumulator + * { + * template + * double operator()(T_iterator first, T_iterator last) const + * { + * double value_ = 0; + * int n_ = 0; + * for (; first != last; ++first, ++n_) + * value_ += *first; + * return value_ / n_; + * } + * }; + * @endcode + * + * @par Example 2: + * This accumulator stops signal emission when a slot returns zero: + * @code + * struct interruptable_accumulator + * { + * template + * bool operator()(T_iterator first, T_iterator last) const + * { + * for (; first != last; ++first, ++n_) + * if (!*first) return false; + * return true; + * } + * }; + * @endcode + * + * @ingroup signal + */ + template + class accumulated : public signal_with_accumulator + { + public: + accumulated() = default; + accumulated(const accumulated& src) + : signal_with_accumulator(src) + { + } + }; + + signal() = default; + + signal(const signal& src) : signal_with_accumulator(src) {} + + signal(signal&& src) + : signal_with_accumulator(std::move(src)) + { + } + + signal& operator=(const signal& src) + { + signal_with_accumulator::operator=(src); + return *this; + } + + signal& operator=(signal&& src) + { + signal_with_accumulator::operator=(std::move(src)); + return *this; + } +}; + +// TODO: When we can break ABI, let signal_base derive from trackable, as in sigc++2, +// and delete trackable_signal_with_accumulator and trackable_signal. +// https://github.com/libsigcplusplus/libsigcplusplus/issues/80 + +/** Signal declaration. + * %trackable_signal_with_accumulator can be used to connect() slots that are invoked + * during subsequent calls to emit(). Any functor or slot + * can be passed into connect() or connect_first(). It is converted into a slot + * implicitly. + * + * If you want to connect one signal to another, use make_slot() + * to retrieve a functor that emits the signal when invoked. + * + * Be careful if you directly pass one signal into the connect() or + * connect_first() method of another: a shallow copy of the signal is made and + * the signal's slots are not disconnected until both the signal + * and its clone are destroyed, which is probably not what you want! + * + * The following template arguments are used: + * - @e T_return The desired return type for the emit() function (may be overridden by the + * accumulator). + * - @e T_arg Argument types used in the definition of emit(). + * - @e T_accumulator The accumulator type used for emission. The default + * @p void means that no accumulator should be used, for example if signal + * emission returns the return value of the last slot invoked. + * + * @newin{3,4} + * + * @ingroup signal + */ +template +class trackable_signal_with_accumulator +: public signal_base +, public trackable +{ +public: + using slot_type = slot; + + /** Add a slot at the end of the list of slots. + * Any functor or slot may be passed into %connect(). + * It will be converted into a slot implicitly. + * The returned connection may be stored for disconnection + * of the slot at some later point. It stays valid until + * the slot is disconnected from the signal. + * std::function<> and C++11 lambda expressions are functors. + * These are examples of functors that can be connected to a signal. + * + * %std::bind() creates a functor, but this functor typically has an + * %operator()() which is a variadic template. + * Our functor_trait can't deduce the result type + * of such a functor. If you first assign the return value of %std::bind() + * to a std::function, you can connect the std::function to a signal. + * + * @param slot_ The slot to add to the list of slots. + * @return A connection. + */ + connection connect(const slot_type& slot_) + { + auto iter = signal_base::connect(slot_); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot at the end of the list of slots. + * @see connect(const slot_type& slot_). + */ + connection connect(slot_type&& slot_) + { + auto iter = signal_base::connect(std::move(slot_)); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot at the beginning of the list of slots. + * Any functor or slot may be passed into %connect_first(). + * It will be converted into a slot implicitly. + * The returned connection may be stored for disconnection + * of the slot at some later point. It stays valid until + * the slot is disconnected from the signal. + * std::function<> and C++11 lambda expressions are functors. + * These are examples of functors that can be connected to a signal. + * + * %std::bind() creates a functor, but this functor typically has an + * %operator()() which is a variadic template. + * Our functor_trait can't deduce the result type + * of such a functor. If you first assign the return value of %std::bind() + * to a std::function, you can connect the std::function to a signal. + * + * @param slot_ The slot to add to the list of slots. + * @return A connection. + * + * @newin{3,6} + */ + connection connect_first(const slot_type& slot_) + { + auto iter = signal_base::connect_first(slot_); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Add a slot at the beginning of the list of slots. + * @see connect_first(const slot_type& slot_). + * + * @newin{3,6} + */ + connection connect_first(slot_type&& slot_) + { + auto iter = signal_base::connect_first(std::move(slot_)); + auto& slot_base = *iter; + return connection(slot_base); + } + + /** Triggers the emission of the signal. + * During signal emission all slots that have been connected + * to the signal are invoked unless they are manually set into + * a blocking state. The parameters are passed on to the slots. + * If @e T_accumulated is not @p void, an accumulator of this type + * is used to process the return values of the slot invocations. + * Otherwise, the return value of the last slot invoked is returned. + * @param a Arguments to be passed on to the slots. + * @return The accumulated return values of the slot invocations. + */ + decltype(auto) emit(type_trait_take_t... a) const + { + using emitter_type = internal::signal_emit; + return emitter_type::emit(impl_, std::forward>(a)...); + } + + /** Triggers the emission of the signal (see emit()). */ + decltype(auto) operator()(type_trait_take_t... a) const + { + return emit(std::forward>(a)...); + } + + /** Creates a functor that calls emit() on this signal. + * + * @code + * sigc::mem_fun(mysignal, &sigc::trackable_signal_with_accumulator::emit) + * @endcode + * yields the same result. + * @return A functor that calls emit() on this signal. + */ + decltype(auto) make_slot() const + { + // TODO: Instead use std::invoke_result<> on the static emitter_type::emit() + using result_type = typename internal::member_method_result< + decltype(&trackable_signal_with_accumulator::emit)>::type; + return bound_mem_functor...) const, + type_trait_take_t...>(*this, &trackable_signal_with_accumulator::emit); + } + + trackable_signal_with_accumulator() = default; + + trackable_signal_with_accumulator(const trackable_signal_with_accumulator& src) + : signal_base(src), trackable(src) + { + } + + trackable_signal_with_accumulator(trackable_signal_with_accumulator&& src) + : signal_base(std::move(src)), trackable(std::move(src)) + { + } + + trackable_signal_with_accumulator& operator=(const trackable_signal_with_accumulator& src) + { + signal_base::operator=(src); + // Don't call trackable::operator=(src). + // It calls notify_callbacks(). This signal is not destroyed. + return *this; + } + + trackable_signal_with_accumulator& operator=(trackable_signal_with_accumulator&& src) + { + signal_base::operator=(std::move(src)); + if (src.impl_ != impl_) + src.notify_callbacks(); + // Don't call trackable::operator=(std::move(src)). + // It calls notify_callbacks(). This signal is not destroyed. + return *this; + } +}; + +/** %trackable_signal can be used to connect() slots that are invoked + * during subsequent calls to emit(). Any functor or slot + * can be passed into connect() or connect_first(). It is converted into a slot + * implicitly. + * + * If you want to connect one signal to another, use make_slot() + * to retrieve a functor that emits the signal when invoked. + * + * Be careful if you directly pass one signal into the connect() or + * connect_first() method of another: a shallow copy of the signal is made and + * the signal's slots are not disconnected until both the signal + * and its clone are destroyed, which is probably not what you want! + * + * The template arguments determine the function signature of + * the emit() function: + * - @e T_return The desired return type of the emit() function. + * - @e T_arg Argument types used in + * the definition of emit(). + * + * For instance, to declare a %trackable_signal whose connected slot returns void and takes + * two parameters of bool and int: + * @code + * sigc::trackable_signal some_signal; + * @endcode + * + * To specify an accumulator type the nested class trackable_signal::accumulated can be used. + * + * @par Example: + * @code + * void foo(int) {} + * sigc::trackable_signal sig; + * sig.connect(sigc::ptr_fun(&foo)); + * sig.emit(19); + * @endcode + * + * @newin{3,4} + * + * @ingroup signal + */ +#ifndef DOXYGEN_SHOULD_SKIP_THIS +template +class trackable_signal; +#endif // DOXYGEN_SHOULD_SKIP_THIS + +template +class trackable_signal +: public trackable_signal_with_accumulator +{ +public: + using accumulator_type = void; + + /** Like @ref sigc::trackable_signal "sigc::trackable_signal" + * but the additional template parameter @e T_accumulator defines the accumulator + * type that should be used. + * + * An accumulator is a functor that uses a pair of special iterators + * to step through a list of slots and calculate a return value + * from the results of the slot invocations. The iterators' operator*() + * executes the slot. The return value is buffered, so that in an expression + * like @code a = (*i) * (*i); @endcode the slot is executed only once. + * + * @par Example 1: + * This accumulator calculates the arithmetic mean value: + * @code + * struct arithmetic_mean_accumulator + * { + * template + * double operator()(T_iterator first, T_iterator last) const + * { + * double value_ = 0; + * int n_ = 0; + * for (; first != last; ++first, ++n_) + * value_ += *first; + * return value_ / n_; + * } + * }; + * @endcode + * + * @par Example 2: + * This accumulator stops signal emission when a slot returns zero: + * @code + * struct interruptable_accumulator + * { + * template + * bool operator()(T_iterator first, T_iterator last) const + * { + * for (; first != last; ++first, ++n_) + * if (!*first) return false; + * return true; + * } + * }; + * @endcode + * + * @newin{3,4} + * + * @ingroup signal + */ + template + class accumulated : public trackable_signal_with_accumulator + { + public: + accumulated() = default; + accumulated(const accumulated& src) + : trackable_signal_with_accumulator(src) + { + } + }; + + trackable_signal() = default; + + trackable_signal(const trackable_signal& src) + : trackable_signal_with_accumulator(src) + { + } + + trackable_signal(trackable_signal&& src) + : trackable_signal_with_accumulator(std::move(src)) + { + } + + trackable_signal& operator=(const trackable_signal& src) + { + trackable_signal_with_accumulator::operator=(src); + return *this; + } + + trackable_signal& operator=(trackable_signal&& src) + { + trackable_signal_with_accumulator::operator=( + std::move(src)); + return *this; + } +}; + +} /* namespace sigc */ + +#endif /* SIGC_SIGNAL_H */ diff --git a/sigc++/signal_base.cc b/sigc++/signal_base.cc index cc8342bb..617bb774 100644 --- a/sigc++/signal_base.cc +++ b/sigc++/signal_base.cc @@ -1,5 +1,4 @@ -/* - * Copyright 2003, The libsigc++ Development Team +/* Copyright 2003 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,67 +11,91 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library; if not, see . */ #include #include // std::unique_ptr -namespace sigc { -namespace internal { +namespace sigc +{ +namespace internal +{ // Data sent from signal_impl::insert() to slot_rep::set_parent() when a slot is -// connected, and then sent from slot_rep::disconnect() to signal_impl::notify() +// connected, and then sent from slot_rep::disconnect() to +// signal_impl::notify_self_and_iter_of_invalidated_slot() // when the slot is disconnected. Bug 167714. -struct self_and_iter +struct self_and_iter : public notifiable { - signal_impl* self_; - signal_impl::iterator_type iter_; + const std::weak_ptr self_; + const signal_impl::iterator_type iter_; - self_and_iter(signal_impl* self, signal_impl::iterator_type iter) - : self_(self), iter_(iter) {} + self_and_iter(const std::weak_ptr& self, const signal_impl::iterator_type& iter) + : self_(self), iter_(iter) + { + } }; -signal_impl::signal_impl() -: ref_count_(0), exec_count_(0), deferred_(false) -{} +signal_impl::signal_impl() : exec_count_(0), deferred_(false) {} + +signal_impl::~signal_impl() +{ + // Disconnect all slots before *this is deleted. + clear(); +} // only MSVC needs this to guarantee that all new/delete are executed from the DLL module #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY -void* signal_impl::operator new(size_t size_) +void* +signal_impl::operator new(size_t size_) { return malloc(size_); } -void signal_impl::operator delete(void* p) +void +signal_impl::operator delete(void* p) { free(p); } #endif -void signal_impl::clear() +void +signal_impl::clear() { - // Don't let signal_impl::notify() erase the slots. It would invalidate the - // iterator in the following loop. + // Don't let signal_impl::notify_self_and_iter_of_invalidated_slot() erase the slots. + // It would invalidate the iterator in the following loop. + // Don't call shared_from_this() here. clear() is called from the destructor. + // When the destructor is executing, shared_ptr's use_count has reached 0, + // and it's no longer possible to get a shared_ptr to this. + const bool during_signal_emission = exec_count_ > 0; const bool saved_deferred = deferred_; - signal_exec exec(this); + signal_impl_exec_holder exec(this); // Disconnect all connected slots before they are deleted. - // signal_impl::notify() will be called and delete the self_and_iter structs. + // signal_impl::notify_self_and_iter_of_invalidated_slot() will be called and + // delete the self_and_iter structs. for (auto& slot : slots_) slot.disconnect(); - deferred_ = saved_deferred; - - slots_.clear(); + // Don't clear slots_ during signal emission. Provided deferred_ is true, + // sweep() will be called from ~signal_impl_holder() after signal emission, + // and it will erase all disconnected slots. + // https://bugzilla.gnome.org/show_bug.cgi?id=784550 + if (!during_signal_emission) + { + deferred_ = saved_deferred; + slots_.clear(); + } } -signal_impl::size_type signal_impl::size() const noexcept +signal_impl::size_type +signal_impl::size() const noexcept { return slots_.size(); } -bool signal_impl::blocked() const noexcept +bool +signal_impl::blocked() const noexcept { for (const auto& slot : const_cast&>(slots_)) { @@ -82,7 +105,8 @@ bool signal_impl::blocked() const noexcept return true; } -void signal_impl::block(bool should_block) noexcept +void +signal_impl::block(bool should_block) noexcept { for (auto& slot : slots_) { @@ -90,213 +114,214 @@ void signal_impl::block(bool should_block) noexcept } } -signal_impl::iterator_type signal_impl::connect(const slot_base& slot_) +signal_impl::iterator_type +signal_impl::connect(const slot_base& slot_) { return insert(slots_.end(), slot_); } -signal_impl::iterator_type signal_impl::connect(slot_base&& slot_) +signal_impl::iterator_type +signal_impl::connect(slot_base&& slot_) { return insert(slots_.end(), std::move(slot_)); } -signal_impl::iterator_type signal_impl::erase(iterator_type i) +signal_impl::iterator_type +signal_impl::connect_first(const slot_base& slot_) { - // Don't let signal_impl::notify() erase the slot. It would be more - // difficult to get the correct return value from signal_impl::erase(). - const bool saved_deferred = deferred_; - signal_exec exec(this); - - // Disconnect the slot before it is deleted. - // signal_impl::notify() will be called and delete the self_and_iter struct. - i->disconnect(); + return insert(slots_.begin(), slot_); +} - deferred_ = saved_deferred; +signal_impl::iterator_type +signal_impl::connect_first(slot_base&& slot_) +{ + return insert(slots_.begin(), std::move(slot_)); +} - return slots_.erase(i); +void +signal_impl::add_notification_to_iter(const signal_impl::iterator_type& iter) +{ + auto si = new self_and_iter(shared_from_this(), iter); + iter->set_parent(si, &signal_impl::notify_self_and_iter_of_invalidated_slot); } - -signal_impl::iterator_type signal_impl::insert(signal_impl::iterator_type i, const slot_base& slot_) + +signal_impl::iterator_type +signal_impl::insert(signal_impl::iterator_type i, const slot_base& slot_) { - auto temp = slots_.insert(i, slot_); - auto si = new self_and_iter(this, temp); - temp->set_parent(si, ¬ify); - return temp; + auto iter = slots_.insert(i, slot_); + add_notification_to_iter(iter); + return iter; } -signal_impl::iterator_type signal_impl::insert(signal_impl::iterator_type i, slot_base&& slot_) +signal_impl::iterator_type +signal_impl::insert(signal_impl::iterator_type i, slot_base&& slot_) { - auto temp = slots_.insert(i, std::move(slot_)); - auto si = new self_and_iter(this, temp); - temp->set_parent(si, ¬ify); - return temp; + auto iter = slots_.insert(i, std::move(slot_)); + add_notification_to_iter(iter); + return iter; } -void signal_impl::sweep() +void +signal_impl::sweep() { // The deletion of a slot may cause the deletion of a signal_base, // a decrementation of ref_count_, and the deletion of this. - // In that case, the deletion of this is deferred to ~signal_exec(). - signal_exec exec(this); + // In that case, the deletion of this is deferred to ~signal_impl_holder(). + signal_impl_holder exec(shared_from_this()); deferred_ = false; auto i = slots_.begin(); while (i != slots_.end()) + { if ((*i).empty()) i = slots_.erase(i); else ++i; + } } -//static -void* signal_impl::notify(void* d) +// static +void +signal_impl::notify_self_and_iter_of_invalidated_slot(notifiable* d) { std::unique_ptr si(static_cast(d)); + auto self = si->self_.lock(); + if (!self) + { + // The signal_impl object is being deleted. The use_count has reached 0. + // Nothing to do here. exec_count_ > 0 and clear() will restore deferred_. + return; + } - if (si->self_->exec_count_ == 0) + if (self->exec_count_ == 0) { // The deletion of a slot may cause the deletion of a signal_base, // a decrementation of si->self_->ref_count_, and the deletion of si->self_. - // In that case, the deletion of si->self_ is deferred to ~signal_exec(). - signal_exec exec(si->self_); - si->self_->slots_.erase(si->iter_); + // In that case, the deletion of si->self_ is deferred to ~signal_impl_holder(). + // https://bugzilla.gnome.org/show_bug.cgi?id=564005#c24 + signal_impl_holder exec(self); + self->slots_.erase(si->iter_); + } + else + { + // This is occurring during signal emission or slot erasure. + // => sweep() will be called from ~signal_impl_holder() after signal emission. + // This is safer because we don't have to care about our + // iterators in emit() and clear(). + self->deferred_ = true; } - else // This is occuring during signal emission or slot erasure. - si->self_->deferred_ = true; // => sweep() will be called from ~signal_exec() after signal emission. - return nullptr; // This is safer because we don't have to care about our - // iterators in emit(), clear(), and erase(). } } /* namespace internal */ -signal_base::signal_base() noexcept -: impl_(nullptr) -{} +signal_base::signal_base() noexcept {} -signal_base::signal_base(const signal_base& src) noexcept -: trackable(), - impl_(src.impl()) -{ - impl_->reference(); -} +signal_base::signal_base(const signal_base& src) noexcept : impl_(src.impl()) {} -signal_base::signal_base(signal_base&& src) -: trackable(std::move(src)), - impl_(std::move(src.impl_)) +signal_base::signal_base(signal_base&& src) : impl_(std::move(src.impl_)) { src.impl_ = nullptr; } -signal_base::~signal_base() -{ - if (impl_) - { - // Disconnect all slots before impl_ is deleted. - // TODO: Move the signal_impl::clear() call to ~signal_impl() when ABI can be broken. - if (impl_->ref_count_ == 1) - impl_->clear(); - - impl_->unreference(); - } -} +signal_base::~signal_base() {} -void signal_base::clear() +void +signal_base::clear() { if (impl_) impl_->clear(); } -signal_base::size_type signal_base::size() const noexcept +signal_base::size_type +signal_base::size() const noexcept { return (impl_ ? impl_->size() : 0); } -bool signal_base::blocked() const noexcept +bool +signal_base::blocked() const noexcept { return (impl_ ? impl_->blocked() : true); } -void signal_base::block(bool should_block) noexcept +void +signal_base::block(bool should_block) noexcept { if (impl_) impl_->block(should_block); } -void signal_base::unblock() noexcept +void +signal_base::unblock() noexcept { if (impl_) impl_->block(false); } -signal_base::iterator_type signal_base::connect(const slot_base& slot_) +signal_base::iterator_type +signal_base::connect(const slot_base& slot_) { return impl()->connect(slot_); } -signal_base::iterator_type signal_base::connect(slot_base&& slot_) +signal_base::iterator_type +signal_base::connect(slot_base&& slot_) { return impl()->connect(std::move(slot_)); } -signal_base::iterator_type signal_base::insert(iterator_type i, const slot_base& slot_) +signal_base::iterator_type +signal_base::connect_first(const slot_base& slot_) { - return impl()->insert(i, slot_); + return impl()->connect_first(slot_); } -signal_base::iterator_type signal_base::insert(iterator_type i, slot_base&& slot_) +signal_base::iterator_type +signal_base::connect_first(slot_base&& slot_) { - return impl()->insert(i, std::move(slot_)); + return impl()->connect_first(std::move(slot_)); } -signal_base::iterator_type signal_base::erase(iterator_type i) +signal_base::iterator_type +signal_base::insert(iterator_type i, const slot_base& slot_) { - return impl()->erase(i); + return impl()->insert(i, slot_); } -signal_base& signal_base::operator=(const signal_base& src) +signal_base::iterator_type +signal_base::insert(iterator_type i, slot_base&& slot_) { - if (src.impl_ == impl_) return *this; + return impl()->insert(i, std::move(slot_)); +} - if (impl_) - { - // Disconnect all slots before impl_ is deleted. - // TODO: Move the signal_impl::clear() call to ~signal_impl() when ABI can be broken. - if (impl_->ref_count_ == 1) - impl_->clear(); +signal_base& +signal_base::operator=(const signal_base& src) +{ + if (src.impl_ == impl_) + return *this; - impl_->unreference(); - } impl_ = src.impl(); - impl_->reference(); return *this; } -signal_base& signal_base::operator=(signal_base&& src) +signal_base& +signal_base::operator=(signal_base&& src) { - if (src.impl_ == impl_) return *this; + if (src.impl_ == impl_) + return *this; - if (impl_) - { - // Disconnect all slots before impl_ is deleted. - // TODO: Move the signal_impl::clear() call to ~signal_impl() when ABI can be broken. - if (impl_->ref_count_ == 1) - impl_->clear(); - - impl_->unreference(); - } - - src.notify_callbacks(); impl_ = src.impl_; src.impl_ = nullptr; return *this; } -internal::signal_impl* signal_base::impl() const +std::shared_ptr +signal_base::impl() const { - if (!impl_) { - impl_ = new internal::signal_impl; - impl_->reference(); // start with a reference count of 1 + if (!impl_) + { + impl_ = std::make_shared(); } return impl_; } diff --git a/sigc++/signal_base.h b/sigc++/signal_base.h index f50a6cb7..8da25508 100644 --- a/sigc++/signal_base.h +++ b/sigc++/signal_base.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,18 +11,17 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library; if not, see . */ -#ifndef _SIGC_SIGNAL_BASE_H_ -#define _SIGC_SIGNAL_BASE_H_ +#ifndef SIGC_SIGNAL_BASE_H +#define SIGC_SIGNAL_BASE_H #include #include +#include //For std::shared_ptr<> #include #include -#include #include #include @@ -36,20 +34,21 @@ namespace internal { /** Implementation of the signal interface. - * signal_impl manages a list of slots. When a slot becomes - * invalid (because some referred object dies), notify() is executed. - * notify() either calls slots_.erase() directly or defers the execution of - * erase() to sweep() when the signal is being emitted. sweep() removes all - * invalid slots from the list. + * signal_impl manages a list of slots. When a slot becomes invalid (because some + * referred object dies), notify_self_and_iter_of_invalidated_slot() is executed. + * notify_self_and_iter_of_invalidated_slot() either calls slots_.erase() directly + * or defers the execution of erase() to sweep() when the signal is being emitted. + * sweep() removes all invalid slots from the list. */ -struct SIGC_API signal_impl +struct SIGC_API signal_impl : public std::enable_shared_from_this { - typedef std::size_t size_type; - typedef std::list slot_list; - typedef slot_list::iterator iterator_type; - typedef slot_list::const_iterator const_iterator_type; + using size_type = std::size_t; + using slot_list = std::list; + using iterator_type = slot_list::iterator; + using const_iterator_type = slot_list::const_iterator; signal_impl(); + ~signal_impl(); signal_impl(const signal_impl& src) = delete; signal_impl& operator=(const signal_impl& src) = delete; @@ -57,41 +56,29 @@ struct SIGC_API signal_impl signal_impl(signal_impl&& src) = delete; signal_impl& operator=(signal_impl&& src) = delete; - // only MSVC needs this to guarantee that all new/delete are executed from the DLL module +// only MSVC needs this to guarantee that all new/delete are executed from the DLL module #ifdef SIGC_NEW_DELETE_IN_LIBRARY_ONLY void* operator new(size_t size_); void operator delete(void* p); #endif - /// Increments the reference counter. - inline void reference() noexcept - { ++ref_count_; } - /// Increments the reference and execution counter. - inline void reference_exec() noexcept - { ++ref_count_; ++exec_count_; } - - /** Decrements the reference counter. - * The object is deleted when the reference counter reaches zero. - */ - inline void unreference() - { if (!(--ref_count_)) delete this; } + inline void reference_exec() noexcept { ++exec_count_; } /** Decrements the reference and execution counter. * Invokes sweep() if the execution counter reaches zero and the * removal of one or more slots has been deferred. */ inline void unreference_exec() - { - if (!(--ref_count_)) delete this; - else if (!(--exec_count_) && deferred_) sweep(); - } + { + if (!(--exec_count_) && deferred_) + sweep(); + } /** Returns whether the list of slots is empty. * @return @p true if the list of slots is empty. */ - inline bool empty() const noexcept - { return slots_.empty(); } + inline bool empty() const noexcept { return slots_.empty(); } /// Empties the list of slots. void clear(); @@ -120,13 +107,13 @@ struct SIGC_API signal_impl */ void block(bool should_block = true) noexcept; - /** Adds a slot at the bottom of the list of slots. + /** Adds a slot at the end of the list of slots. * @param slot_ The slot to add to the list of slots. * @return An iterator pointing to the new slot in the list. */ iterator_type connect(const slot_base& slot_); - /** Adds a slot at the bottom of the list of slots. + /** Adds a slot at the end of the list of slots. * @param slot_ The slot to add to the list of slots. * @return An iterator pointing to the new slot in the list. * @@ -134,6 +121,22 @@ struct SIGC_API signal_impl */ iterator_type connect(slot_base&& slot_); + /** Adds a slot at the beginning of the list of slots. + * @param slot_ The slot to add to the list of slots. + * @return An iterator pointing to the new slot in the list. + * + * @newin{3,6} + */ + iterator_type connect_first(const slot_base& slot_); + + /** Adds a slot at the beginning of the list of slots. + * @param slot_ The slot to add to the list of slots. + * @return An iterator pointing to the new slot in the list. + * + * @newin{3,6} + */ + iterator_type connect_first(slot_base&& slot_); + /** Adds a slot at the given position into the list of slots. * @param i An iterator indicating the position where @p slot_ should be inserted. * @param slot_ The slot to add to the list of slots. @@ -150,15 +153,10 @@ struct SIGC_API signal_impl */ iterator_type insert(iterator_type i, slot_base&& slot_); - /** Removes the slot at the given position from the list of slots. - * @param i An iterator pointing to the slot to be removed. - * @return An iterator pointing to the slot in the list after the one removed. - */ - iterator_type erase(iterator_type i); - /// Removes invalid slots from the list of slots. void sweep(); +private: /** Callback that is executed when some slot becomes invalid. * This callback is registered in every slot when inserted into * the list of slots. It is executed when a slot becomes invalid @@ -167,13 +165,15 @@ struct SIGC_API signal_impl * erase() to sweep() when the signal is being emitted. * @param d A local structure, created in insert(). */ - static void* notify(void* d); + static void notify_self_and_iter_of_invalidated_slot(notifiable* d); - /** Reference counter. - * The object is destroyed when @em ref_count_ reaches zero. - */ - short ref_count_; + void add_notification_to_iter(const signal_impl::iterator_type& iter); + +public: + /// The list of slots. + std::list slots_; +private: /** Execution counter. * Indicates whether the signal is being emitted. */ @@ -181,68 +181,61 @@ struct SIGC_API signal_impl /// Indicates whether the execution of sweep() is being deferred. bool deferred_; - - /// The list of slots. - std::list slots_; }; -/// Exception safe sweeper for cleaning up invalid slots on the slot list. -struct SIGC_API signal_exec +struct SIGC_API signal_impl_exec_holder { - /// The parent sigc::signal_impl object. - signal_impl* sig_; - - /** Increments the reference and execution counter of the parent sigc::signal_impl object. + /** Increments the execution counter of the parent sigc::signal_impl object. * @param sig The parent sigc::signal_impl object. */ - inline signal_exec(const signal_impl* sig) noexcept - : sig_(const_cast(sig) ) - { sig_->reference_exec(); } + inline explicit signal_impl_exec_holder(signal_impl* sig) noexcept : sig_(sig) + { + sig_->reference_exec(); + } + + signal_impl_exec_holder(const signal_impl_exec_holder& src) = delete; + signal_impl_exec_holder operator=(const signal_impl_exec_holder& src) = delete; + + signal_impl_exec_holder(signal_impl_exec_holder&& src) = delete; + signal_impl_exec_holder operator=(signal_impl_exec_holder&& src) = delete; /// Decrements the reference and execution counter of the parent sigc::signal_impl object. - inline ~signal_exec() - { sig_->unreference_exec(); } + inline ~signal_impl_exec_holder() { sig_->unreference_exec(); } + +protected: + /// The parent sigc::signal_impl object. + signal_impl* sig_; }; -/** Temporary slot list used during signal emission. - * Through evolution this class is slightly misnamed. It is now - * an index into the slot_list passed into it. It simply keeps track - * of where the end of this list was at construction, and pretends that's - * the end of your list. This way you may connect during emission without - * inadvertently entering an infinite loop, as well as make other - * modifications to the slot_list at your own risk. - */ -struct temp_slot_list +/// Exception safe sweeper for cleaning up invalid slots on the slot list. +struct SIGC_API signal_impl_holder { - typedef signal_impl::slot_list slot_list; - typedef signal_impl::iterator_type iterator; - typedef signal_impl::const_iterator_type const_iterator; - - temp_slot_list(slot_list &slots) : slots_(slots) + /** Increments the reference and execution counter of the parent sigc::signal_impl object. + * @param sig The parent sigc::signal_impl object. + */ + inline signal_impl_holder(const std::shared_ptr& sig) noexcept + : sig_(sig), exec_holder_(sig.get()) { - placeholder = slots_.insert(slots_.end(), slot_base()); } - ~temp_slot_list() - { - slots_.erase(placeholder); - } + signal_impl_holder(const signal_impl_holder& src) = delete; + signal_impl_holder operator=(const signal_impl_holder& src) = delete; - iterator begin() { return slots_.begin(); } - iterator end() { return placeholder; } - const_iterator begin() const { return slots_.begin(); } - const_iterator end() const { return placeholder; } + signal_impl_holder(signal_impl_holder&& src) = delete; + signal_impl_holder operator=(signal_impl_holder&& src) = delete; -private: - slot_list &slots_; - slot_list::iterator placeholder; +protected: + /// The parent sigc::signal_impl object. + const std::shared_ptr sig_; + signal_impl_exec_holder exec_holder_; }; - -} /* namespace internal */ +} /* namespace internal */ /** @defgroup signal Signals - * Use sigc::signal::connect() with sigc::mem_fun() and sigc::ptr_fun() to connect a method or function with a signal. + * Use @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()" + * or @ref sigc::signal_with_accumulator::connect_first() "sigc::signal::connect_first()" + * with sigc::mem_fun() and sigc::ptr_fun() to connect a method or function with a signal. * * @code * signal_clicked.connect( sigc::mem_fun(*this, &MyWindow::on_clicked) ); @@ -254,8 +247,9 @@ struct temp_slot_list * If the type of your object inherits from sigc::trackable the method is disconnected * automatically when your object is destroyed. * - * When signals are copied they share the underlying information, - * so you can have a protected/private sigc::signal member and a public accessor method. + * When signals are copied they share the underlying information, so you can have + * a protected/private @ref sigc::signal "sigc::signal" + * member and a public accessor method. * A sigc::signal is a kind of reference-counting pointer. It's similar to * std::shared_ptr<>, although sigc::signal is restricted to holding a pointer to * a sigc::internal::signal_impl object that contains the implementation of the signal. @@ -264,7 +258,7 @@ struct temp_slot_list * class MyClass * { * public: - * typedef sigc::signal MySignalType; + * using MySignalType = sigc::signal; * MySignalType get_my_signal() { return m_my_signal; } * private: * MySignalType m_my_signal; @@ -281,27 +275,53 @@ struct temp_slot_list * if the given functor or closure cannot be invoked with the * parameter list of the signal to connect to. * - * Almost any functor with the correct signature can be converted to a sigc::slot - * and connected to a signal. See @ref slot "Slots" and sigc::signal::connect(). + * Almost any functor with the correct signature can be converted to + * a @ref sigc::slot "sigc::slot" + * and connected to a signal. See @ref slot "Slots" and + * @ref sigc::signal_with_accumulator::connect() "sigc::signal::connect()". + * + * Use @ref sigc::signal_connect() to connect a method or function to a signal + * without having to explicitly write the required template parameters in case + * of method or function overloading. + * + * @code + * sigc::signal sig; + * void fun(int); + * void fun(double); + * sig.connect(sigc::ptr_fun(fun)); + * // or more simply: + * sigc::signal_connect(sig, fun); + * @endcode + * + * It can also be used as a replacement for calling signal::connect() with a + * sigc::mem_fun() or a sigc::ptr_fun(). */ -/** Base class for the sigc::signal# templates. - * signal_base integrates most of the interface of the derived sigc::signal# - * templates. The implementation, however, resides in sigc::internal::signal_impl. - * A sigc::internal::signal_impl object is dynamically allocated from signal_base +// TODO: When we can break ABI, let signal_base derive from trackable again, +// as in sigc++2. Otherwise the slot returned from signal::make_slot() +// is not automatically disconnected when the signal is deleted. +// And delete trackable_signal_with_accumulator and trackable_signal. +// https://github.com/libsigcplusplus/libsigcplusplus/issues/80 + +/** Base class for the @ref sigc::signal "sigc::signal" template. + * %signal_base integrates most of the interface of the derived + * @ref sigc::signal "sigc::signal" template. + * The implementation, however, resides in sigc::internal::signal_impl. + * A sigc::internal::signal_impl object is dynamically allocated from %signal_base * when first connecting a slot to the signal. This ensures that empty signals * don't waste memory. * - * sigc::internal::signal_impl is reference-counted. When a sigc::signal# object + * sigc::internal::signal_impl is reference-counted. + * When a @ref sigc::signal "sigc::signal" object * is copied, the reference count of its sigc::internal::signal_impl object is - * incremented. Both sigc::signal# objects then refer to the same - * sigc::internal::signal_impl object. + * incremented. Both @ref sigc::signal "sigc::signal" objects + * then refer to the same sigc::internal::signal_impl object. * * @ingroup signal */ -struct SIGC_API signal_base : public trackable +struct SIGC_API signal_base { - typedef std::size_t size_type; + using size_type = std::size_t; signal_base() noexcept; @@ -318,8 +338,7 @@ struct SIGC_API signal_base : public trackable /** Returns whether the list of slots is empty. * @return @p true if the list of slots is empty. */ - inline bool empty() const noexcept - { return (!impl_ || impl_->empty()); } + inline bool empty() const noexcept { return (!impl_ || impl_->empty()); } /// Empties the list of slots. void clear(); @@ -356,10 +375,10 @@ struct SIGC_API signal_base : public trackable void unblock() noexcept; protected: - typedef internal::signal_impl::iterator_type iterator_type; + using iterator_type = internal::signal_impl::iterator_type; /** Adds a slot at the end of the list of slots. - * With connect(), slots can also be added during signal emission. + * With %connect(), slots can also be added during signal emission. * In this case, they won't be executed until the next emission occurs. * @param slot_ The slot to add to the list of slots. * @return An iterator pointing to the new slot in the list. @@ -367,7 +386,7 @@ struct SIGC_API signal_base : public trackable iterator_type connect(const slot_base& slot_); /** Adds a slot at the end of the list of slots. - * With connect(), slots can also be added during signal emission. + * With %connect(), slots can also be added during signal emission. * In this case, they won't be executed until the next emission occurs. * @param slot_ The slot to add to the list of slots. * @return An iterator pointing to the new slot in the list. @@ -376,6 +395,26 @@ struct SIGC_API signal_base : public trackable */ iterator_type connect(slot_base&& slot_); + /** Adds a slot at the beginning of the list of slots. + * With %connect_first(), slots can also be added during signal emission. + * In this case, they won't be executed until the next emission occurs. + * @param slot_ The slot to add to the list of slots. + * @return An iterator pointing to the new slot in the list. + * + * @newin{3,6} + */ + iterator_type connect_first(const slot_base& slot_); + + /** Adds a slot at the beginning of the list of slots. + * With %connect_fist(), slots can also be added during signal emission. + * In this case, they won't be executed until the next emission occurs. + * @param slot_ The slot to add to the list of slots. + * @return An iterator pointing to the new slot in the list. + * + * @newin{3,6} + */ + iterator_type connect_first(slot_base&& slot_); + /** Adds a slot at the given position into the list of slots. * Note that this function does not work during signal emission! * @param i An iterator indicating the position where @e slot_ should be inserted. @@ -394,22 +433,15 @@ struct SIGC_API signal_base : public trackable */ iterator_type insert(iterator_type i, slot_base&& slot_); - /** Removes the slot at the given position from the list of slots. - * Note that this function does not work during signal emission! - * @param i An iterator pointing to the slot to be removed. - * @return An iterator pointing to the slot in the list after the one removed. - */ - iterator_type erase(iterator_type i); - /** Returns the signal_impl object encapsulating the list of slots. * @return The signal_impl object encapsulating the list of slots. */ - internal::signal_impl* impl() const; + std::shared_ptr impl() const; /// The signal_impl object encapsulating the slot list. - mutable internal::signal_impl* impl_; + mutable std::shared_ptr impl_; }; -} //namespace sigc +} // namespace sigc -#endif /* _SIGC_SIGNAL_BASE_H_ */ +#endif /* SIGC_SIGNAL_BASE_H */ diff --git a/sigc++/signal_connect.h b/sigc++/signal_connect.h new file mode 100644 index 00000000..c00516f3 --- /dev/null +++ b/sigc++/signal_connect.h @@ -0,0 +1,76 @@ +/* Copyright 2024, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_SIGNAL_CONNECT_H +#define SIGC_SIGNAL_CONNECT_H + +#include +#include +#include + +namespace sigc +{ + +/** Connect a function to a signal + * @param signal The signal to connect to. + * @param fun The function that should be wrapped. + * @return A connection. + * + * @newin{3,8} + * @ingroup signal + */ +template +inline connection +signal_connect(signal& signal, T_return (*fun)(T_arg...)) +{ + return signal.connect(ptr_fun(fun)); +} + +/** Connect a non-const method to a signal + * @param signal The signal to connect to. + * @param obj Reference to object instance the functor should operate on. + * @param fun Pointer to method that should be wrapped. + * @return A connection. + * + * @newin{3,8} + * @ingroup signal + */ +template +inline connection +signal_connect(signal& signal, T_obj& obj, T_return (T_obj::*fun)(T_arg...)) +{ + return signal.connect(mem_fun(obj, fun)); +} + +/** Connect a const method to a signal + * @param signal The signal to connect to. + * @param obj Reference to object instance the functor should operate on. + * @param fun Pointer to method that should be wrapped. + * @return A connection. + * + * @newin{3,8} + * @ingroup signal + */ +template +inline connection +signal_connect(signal& signal, const T_obj& obj, T_return (T_obj::*fun)(T_arg...) const) +{ + return signal.connect(mem_fun(obj, fun)); +} + +} /* namespace sigc */ + +#endif /* SIGC_SIGNAL_CONNECT_H */ diff --git a/sigc++/slot.h b/sigc++/slot.h index 2490f123..b4ef42c8 100644 --- a/sigc++/slot.h +++ b/sigc++/slot.h @@ -1,4 +1,4 @@ -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -13,8 +13,8 @@ * You should have received a copy of the GNU Lesser General Public * License along with this library. If not, see . */ -#ifndef _SIGC_SLOT_H_ -#define _SIGC_SLOT_H_ +#ifndef SIGC_SLOT_H +#define SIGC_SLOT_H #include -#endif /* _SIGC_SLOT_H_ */ +#endif /* SIGC_SLOT_H */ diff --git a/sigc++/trackable.cc b/sigc++/trackable.cc index 135d1caf..e4e3da51 100644 --- a/sigc++/trackable.cc +++ b/sigc++/trackable.cc @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,9 +11,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ #include @@ -22,15 +19,11 @@ namespace sigc { -trackable::trackable() noexcept -: callback_list_(nullptr) -{} +trackable::trackable() noexcept : callback_list_(nullptr) {} /* Don't copy the notification list. The objects watching src don't need to be notified when the new object dies. */ -trackable::trackable(const trackable& /*src*/) noexcept -: callback_list_(nullptr) -{} +trackable::trackable(const trackable& /*src*/) noexcept : callback_list_(nullptr) {} // Don't move the notification list. // The objects watching src don't need to be notified when the new object dies. @@ -38,25 +31,26 @@ trackable::trackable(const trackable& /*src*/) noexcept // // If trackable's move constructor is modified, check if Glib::Object's // move constructor should be modified similarly. -trackable::trackable(trackable&& src) -: callback_list_(nullptr) +trackable::trackable(trackable&& src) noexcept : callback_list_(nullptr) { src.notify_callbacks(); } -trackable& trackable::operator=(const trackable& src) +trackable& +trackable::operator=(const trackable& src) { - if(this != &src) - notify_callbacks(); //Make sure that we have finished with existing stuff before replacing it. - + if (this != &src) + notify_callbacks(); // Make sure that we have finished with existing stuff before replacing it. + return *this; } -trackable& trackable::operator=(trackable&& src) +trackable& +trackable::operator=(trackable&& src) noexcept { - if(this != &src) + if (this != &src) { - notify_callbacks(); //Make sure that we have finished with existing stuff before replacing it. + notify_callbacks(); // Make sure that we have finished with existing stuff before replacing it. src.notify_callbacks(); // src probably becomes useless. } return *this; @@ -67,25 +61,27 @@ trackable::~trackable() notify_callbacks(); } -void trackable::add_destroy_notify_callback(void* data, func_destroy_notify func) const +void +trackable::add_destroy_notify_callback(notifiable* data, func_destroy_notify func) const { callback_list()->add_callback(data, func); } -void trackable::remove_destroy_notify_callback(void* data) const +void +trackable::remove_destroy_notify_callback(notifiable* data) const { callback_list()->remove_callback(data); } -void trackable::notify_callbacks() +void +trackable::notify_callbacks() { - if (callback_list_) - delete callback_list_; //This invokes all of the callbacks. - + delete callback_list_; // This invokes all of the callbacks. callback_list_ = nullptr; } -internal::trackable_callback_list* trackable::callback_list() const +internal::trackable_callback_list* +trackable::callback_list() const { if (!callback_list_) callback_list_ = new internal::trackable_callback_list; @@ -93,7 +89,6 @@ internal::trackable_callback_list* trackable::callback_list() const return callback_list_; } - namespace internal { @@ -102,41 +97,50 @@ trackable_callback_list::~trackable_callback_list() clearing_ = true; for (auto& callback : callbacks_) + { if (callback.func_) callback.func_(callback.data_); + } } -void trackable_callback_list::add_callback(void* data, func_destroy_notify func) +void +trackable_callback_list::add_callback(notifiable* data, func_destroy_notify func) { - if (!clearing_) // TODO: Is it okay to silently ignore attempts to add dependencies when the list is being cleared? - // I'd consider this a serious application bug, since the app is likely to segfault. - // But then, how should we handle it? Throw an exception? Martin. - callbacks_.push_back(trackable_callback(data, func)); + // TODO: Is it okay to silently ignore attempts to add dependencies when the list + // is being cleared? + // I'd consider this a serious application bug, since the app is likely to segfault. + // But then, how should we handle it? Throw an exception? Martin. + if (!clearing_) + callbacks_.emplace_back(trackable_callback(data, func)); } -void trackable_callback_list::clear() +void +trackable_callback_list::clear() { clearing_ = true; for (auto& callback : callbacks_) - if (callback.func_) + { + if (callback.func_) callback.func_(callback.data_); + } callbacks_.clear(); clearing_ = false; } -void trackable_callback_list::remove_callback(void* data) +void +trackable_callback_list::remove_callback(notifiable* data) { - for (callback_list::iterator i = callbacks_.begin(); i != callbacks_.end(); ++i) + for (auto i = callbacks_.begin(); i != callbacks_.end(); ++i) { auto& callback = *i; if (callback.data_ == data && callback.func_ != nullptr) { - //Don't remove a list element while the list is being cleared. - //It could invalidate the iterator in ~trackable_callback_list() or clear(). - //But it may be necessary to invalidate the callback. See bug 589202. + // Don't remove a list element while the list is being cleared. + // It could invalidate the iterator in ~trackable_callback_list() or clear(). + // But it may be necessary to invalidate the callback. See bug 589202. if (clearing_) callback.func_ = nullptr; else diff --git a/sigc++/trackable.h b/sigc++/trackable.h index 6f9b0178..c985f68a 100644 --- a/sigc++/trackable.h +++ b/sigc++/trackable.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,20 +11,22 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_TRACKABLE_HPP_ -#define _SIGC_TRACKABLE_HPP_ +#ifndef SIGC_TRACKABLE_HPP +#define SIGC_TRACKABLE_HPP #include #include -namespace sigc { +namespace sigc +{ + +struct notifiable; -namespace internal { +namespace internal +{ -typedef void* (*func_destroy_notify) (void* data); +using func_destroy_notify = void (*)(notifiable* data); /** Destroy notification callback. * A destroy notification callback consists of a data pointer and a @@ -35,10 +36,11 @@ typedef void* (*func_destroy_notify) (void* data); */ struct SIGC_API trackable_callback { - void* data_; + notifiable* data_; func_destroy_notify func_; - trackable_callback(void* data, func_destroy_notify func) noexcept - : data_(data), func_(func) {} + trackable_callback(notifiable* data, func_destroy_notify func) noexcept : data_(data), func_(func) + { + } }; /** Callback list. @@ -52,21 +54,20 @@ struct SIGC_API trackable_callback_list /** Add a callback function. * @param data Data that will be sent as a parameter to teh callback function. * @param func The callback function. - * + * */ - void add_callback(void* data, func_destroy_notify func); + void add_callback(notifiable* data, func_destroy_notify func); /** Remove the callback which has this data associated with it. * @param data The data that was given as a parameter to add_callback(). */ - void remove_callback(void* data); + void remove_callback(notifiable* data); /** This invokes all of the callback functions. */ void clear(); - trackable_callback_list() - : clearing_(false) {} + trackable_callback_list() : clearing_(false) {} trackable_callback_list(const trackable_callback_list& src) = delete; trackable_callback_list& operator=(const trackable_callback_list& src) = delete; @@ -78,13 +79,17 @@ struct SIGC_API trackable_callback_list ~trackable_callback_list(); private: - typedef std::list callback_list; + using callback_list = std::list; callback_list callbacks_; - bool clearing_; + bool clearing_; }; } /* namespace internal */ +struct SIGC_API notifiable +{ + using func_destroy_notify = internal::func_destroy_notify; +}; /** Base class for objects with auto-disconnection. * trackable must be inherited when objects shall automatically @@ -106,7 +111,7 @@ struct SIGC_API trackable_callback_list * * @ingroup signal */ -struct SIGC_API trackable +struct SIGC_API trackable : public notifiable { // Concerning noexcept specifications: // libsigc++ does not have complete control of what happens when notify_callbacks() @@ -117,31 +122,31 @@ struct SIGC_API trackable trackable(const trackable& src) noexcept; - trackable(trackable&& src); + trackable(trackable&& src) noexcept; trackable& operator=(const trackable& src); - trackable& operator=(trackable&& src); + trackable& operator=(trackable&& src) noexcept; ~trackable(); - /*virtual ~trackable() {} */ /* we would need a virtual dtor for users - who insist on using "trackable*" as - pointer type for their own derived objects */ + /*virtual ~trackable() {} */ /* we would need a virtual dtor for users + who insist on using "trackable*" as + pointer type for their own derived objects */ + + using func_destroy_notify = internal::func_destroy_notify; - typedef internal::func_destroy_notify func_destroy_notify; - /** Add a callback that is executed (notified) when the trackable object is detroyed. * @param data Passed into func upon notification. * @param func Callback executed upon destruction of the object. */ - void add_destroy_notify_callback(void* data, func_destroy_notify func) const; + void add_destroy_notify_callback(notifiable* data, func_destroy_notify func) const; /** Remove a callback previously installed with add_destroy_notify_callback(). * The callback is not executed. * @param data Parameter passed into previous call to add_destroy_notify_callback(). */ - void remove_destroy_notify_callback(void* data) const; + void remove_destroy_notify_callback(notifiable* data) const; /// Execute and remove all previously installed callbacks. void notify_callbacks(); @@ -158,4 +163,4 @@ struct SIGC_API trackable } /* namespace sigc */ -#endif /* _SIGC_TRACKABLE_HPP_ */ +#endif /* SIGC_TRACKABLE_HPP */ diff --git a/sigc++/tuple-utils/tuple_cdr.h b/sigc++/tuple-utils/tuple_cdr.h new file mode 100644 index 00000000..6cc41e58 --- /dev/null +++ b/sigc++/tuple-utils/tuple_cdr.h @@ -0,0 +1,71 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_TUPLE_UTILS_TUPLE_CDR_H +#define SIGC_TUPLE_UTILS_TUPLE_CDR_H + +#include +#include +#include + +namespace sigc::internal +{ + +/** + * Get the type of a tuple without the first item. + */ +template +struct tuple_type_cdr; // primary template is not defined + +// Partial specialization for tuples of at least one element: +template +struct tuple_type_cdr> +{ + using type = std::tuple; +}; + +namespace detail +{ + +template +constexpr decltype(auto) +tuple_cdr_impl(T&& t, std::index_sequence<0, I...>) +{ + using cdr = typename tuple_type_cdr>::type; + return cdr(std::get(std::forward(t))...); +} + +} // detail namespace + +/** + * Get the a tuple without the first item. + * This is analogous to std::tuple_cat(). + */ +template +constexpr decltype(auto) +tuple_cdr(T&& t) +{ + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + + static_assert(size != 0, "tuple size must be non-zero"); + using seq = std::make_index_sequence; + return detail::tuple_cdr_impl(std::forward(t), seq{}); +} + +} // namespace sigc::internal + +#endif // SIGC_TUPLE_UTILS_TUPLE_CDR_H diff --git a/sigc++/tuple-utils/tuple_end.h b/sigc++/tuple-utils/tuple_end.h new file mode 100644 index 00000000..7fa2e132 --- /dev/null +++ b/sigc++/tuple-utils/tuple_end.h @@ -0,0 +1,86 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_TUPLE_UTILS_TUPLE_END_H +#define SIGC_TUPLE_UTILS_TUPLE_END_H + +#include + +namespace sigc::internal +{ + +namespace detail +{ + +template +struct tuple_type_end_impl +{ + using type = typename tuple_type_end_impl>::type, + remove_from_start - 1>::type; +}; + +template +struct tuple_type_end_impl +{ + using type = T; +}; + +} // detail namespace + +/** + * Get the type of a tuple with the last @a len types of the original. + */ +template +struct tuple_type_end : detail::tuple_type_end_impl::value - len> +{ +}; + +/** + * Get the tuple with the last @a len items of the original. + */ +template +constexpr decltype(auto) // typename tuple_type_end::type +tuple_end(T&& t) +{ + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + static_assert(len <= size, "The tuple size must be greater than or equal to the length."); + + if constexpr (len == 0) + { + // Prevent 'unreferenced formal parameter' warning from MSVC by 'using' t + static_cast(t); + // Recursive calls to tuple_cdr() would result in this eventually, + // but this avoids the extra work: + return std::tuple<>(); + } + else if constexpr (size - len == 0) + { + return std::forward(t); + } + else if constexpr (size - len == 1) + { + return tuple_cdr(std::forward(t)); + } + else + { + return tuple_end(tuple_cdr(std::forward(t))); + } +} + +} // namespace sigc::internal; + +#endif // SIGC_TUPLE_UTILS_TUPLE_END_H diff --git a/sigc++/tuple-utils/tuple_for_each.h b/sigc++/tuple-utils/tuple_for_each.h new file mode 100644 index 00000000..97ffd901 --- /dev/null +++ b/sigc++/tuple-utils/tuple_for_each.h @@ -0,0 +1,117 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_TUPLE_UTILS_TUPLE_FOR_EACH_H +#define SIGC_TUPLE_UTILS_TUPLE_FOR_EACH_H + +#include + +namespace sigc +{ + +namespace internal +{ + +namespace detail +{ + +template class T_visitor, std::size_t size_from_index, typename... T_extras> +struct tuple_for_each_impl +{ + template + constexpr static void tuple_for_each(T&& t, T_extras&&... extras) + { + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + static_assert(size > 1, "size must be more than 0."); + + constexpr auto index = size - size_from_index; + static_assert(index >= 0, "unexpected index."); + + using element_type = typename std::tuple_element>::type; + T_visitor::visit(std::get(t), std::forward(extras)...); + + tuple_for_each_impl::tuple_for_each( + std::forward(t), std::forward(extras)...); + } +}; + +template class T_visitor, typename... T_extras> +struct tuple_for_each_impl +{ + template + constexpr static void tuple_for_each(T&& t, T_extras&&... extras) + { + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + static_assert(size > 0, "size must be more than 0."); + + constexpr auto index = size - 1; + static_assert(index >= 0, "unexpected index."); + + using element_type = typename std::tuple_element>::type; + T_visitor::visit( + std::get(std::forward(t)), std::forward(extras)...); + } +}; + +template class T_visitor, typename... T_extras> +struct tuple_for_each_impl +{ + template + constexpr static void tuple_for_each(T&& /* t */, T_extras&&... /* extras */) + { + // Do nothing because the tuple has no elements. + } +}; + +} // detail namespace + +/** + * Call the @e T_Visitor functors visit() method for each element, + * from the first to the last. + * + * @tparam T_visitor should be a template that has a static visit() method. + * @tparam T the tuple type. + * @tparam T_extras the types of any extra arguments to pass to @e T_Visitor's + * visit() method. + * @param t The tuple whose elements should be visited. + * @param extras Any extra arguments to pass to @e T_Visitor's visit() method. + */ +template class T_visitor, typename T, typename... T_extras> +constexpr void +tuple_for_each(T&& t, T_extras&&... extras) +{ + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + + if constexpr (size != 0) + { + detail::tuple_for_each_impl::tuple_for_each( + std::forward(t), std::forward(extras)...); + } + else + { + // Prevent 'unreferenced formal parameter' warning from MSVC by 'using' t + static_cast(t); + } +} + +} // namespace internal + +} // namespace sigc + +#endif // SIGC_TUPLE_UTILS_TUPLE_FOR_EACH_H diff --git a/sigc++/tuple-utils/tuple_start.h b/sigc++/tuple-utils/tuple_start.h new file mode 100644 index 00000000..3df08588 --- /dev/null +++ b/sigc++/tuple-utils/tuple_start.h @@ -0,0 +1,87 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_TUPLE_UTILS_TUPLE_START_H +#define SIGC_TUPLE_UTILS_TUPLE_START_H + +#include +#include + +namespace sigc::internal +{ + +namespace detail +{ + +template +struct tuple_type_start_impl; + +template +struct tuple_type_start_impl> +{ + using type = std::tuple::type...>; +}; + +} // detail namespace + +/** + * Get the type of a tuple with just the first @len items. + */ +template +struct tuple_type_start : detail::tuple_type_start_impl> +{ +}; + +namespace detail +{ + +template +struct tuple_start_impl; + +template +struct tuple_start_impl> +{ + static constexpr decltype(auto) tuple_start(T&& t) + { + constexpr auto size = std::tuple_size>::value; + constexpr auto len = sizeof...(I); + static_assert(len <= size, "The tuple size must be greater than or equal to the length."); + + using start = typename tuple_type_start, len>::type; + return start(std::get(std::forward(t))...); + } +}; + +} // detail namespace + +/** + * Get the tuple with the last @a len items of the original. + */ +template +constexpr decltype(auto) // typename tuple_type_end::type +tuple_start(T&& t) +{ + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + static_assert(len <= size, "The tuple size must be greater than or equal to the length."); + + return detail::tuple_start_impl>::tuple_start( + std::forward(t)); +} + +} // namespace sigc::internal; + +#endif // SIGC_TUPLE_UTILS_TUPLE_START_H diff --git a/sigc++/tuple-utils/tuple_transform_each.h b/sigc++/tuple-utils/tuple_transform_each.h new file mode 100644 index 00000000..a4064fa6 --- /dev/null +++ b/sigc++/tuple-utils/tuple_transform_each.h @@ -0,0 +1,108 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3.0 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H +#define SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H + +#include +#include +#include +#include + +namespace sigc::internal +{ + +namespace detail +{ + +template class T_transformer, std::size_t size_from_index> +struct tuple_transform_each_impl +{ + // TODO: Avoid the need to pass t_original all the way into the recursion? + template + constexpr static decltype(auto) tuple_transform_each(T_current&& t, T_original& t_original) + { + if constexpr (size_from_index == 0) + { + // Prevent 'unreferenced formal parameter' warning from MSVC by 'using' + // t_original + static_cast(t_original); + // Do nothing because the tuple has no elements. + return std::forward(t); + } + else + { // TODO: Should this compile without using else to contain the alternative code? + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + constexpr auto index = size - size_from_index; + static_assert(index >= 0, "unexpected index."); + + using from_element_type = typename std::tuple_element>::type; + using to_element_type = + typename std::invoke_result::transform), + from_element_type&>::type; + // Tuples which are input data to std::tuple_cat() should not be declared const. + // Some versions of libc++ has a bug in std::tuple_cat(): All output elements + // coming from a const tuple become const. + // https://github.com/libsigcplusplus/libsigcplusplus/issues/25 + auto t_element = std::tuple( + T_transformer::transform(std::get(t_original))); + + if constexpr (size_from_index == 1) + { + auto tuple_rest = tuple_start(std::forward(t)); + return std::tuple_cat(tuple_rest, t_element); + } + else + { + auto t_start = tuple_start(std::forward(t)); + + // t_end's elements will be copies of the elements in t, so this method's + // caller won't see the changes made in the subsequent call of + // tuple_transform_each() on those copies. That's why we pass t_original + // through too, so we can modify that directly. + // the const version (tuple_transform_each_const()) doesn't have to worry + // about this, though avoiding copying would be more efficient. + auto t_end = tuple_end(t); + + auto t_with_transformed_element = std::tuple_cat(t_start, t_element, t_end); + return tuple_transform_each_impl::tuple_transform_each( + t_with_transformed_element, t_original); + } + } + } +}; + +} // detail namespace + +/** + * Get a tuple with each element having the transformed value of the element + * in the original tuple. + */ +template class T_transformer, typename T> +constexpr decltype(auto) +tuple_transform_each(T&& t) +{ + // We use std::decay_t<> because tuple_size is not defined for references. + constexpr auto size = std::tuple_size>::value; + + return detail::tuple_transform_each_impl::tuple_transform_each( + std::forward(t), t); +} + +} // namespace sigc::internal + +#endif // SIGC_TUPLE_UTILS_TUPLE_TRANSFORM_EACH_H diff --git a/sigc++/type_traits.h b/sigc++/type_traits.h index 41b2a41f..cf6d1eb1 100644 --- a/sigc++/type_traits.h +++ b/sigc++/type_traits.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,51 +11,56 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - * + * License along with this library; if not, see . */ -#ifndef _SIGC_TYPE_TRAIT_H_ -#define _SIGC_TYPE_TRAIT_H_ +#ifndef SIGC_TYPE_TRAIT_H +#define SIGC_TYPE_TRAIT_H #include +namespace sigc +{ -namespace sigc { - -template +template struct type_trait { - typedef T_type& pass; - typedef const T_type& take; + using pass = T_type&; + using take = const T_type&; }; -template +template struct type_trait { - typedef T_type*& pass; - typedef const T_type*& take; + using pass = T_type*&; + using take = const T_type*&; }; -template +template struct type_trait { - typedef T_type& pass; - typedef T_type& take; + using pass = T_type&; + using take = T_type&; }; -template +template struct type_trait { - typedef const T_type& pass; - typedef const T_type& take; + using pass = const T_type&; + using take = const T_type&; +}; + +template +struct type_trait +{ + using pass = T_type&&; + using take = T_type&&; }; template<> struct type_trait { - typedef void pass; - typedef void take; + using pass = void; + using take = void; }; template @@ -67,4 +71,4 @@ using type_trait_take_t = typename type_trait::take; } /* namespace sigc */ -#endif /* _SIGC_TYPE_TRAIT_H_ */ +#endif /* SIGC_TYPE_TRAIT_H */ diff --git a/sigc++/visit_each.h b/sigc++/visit_each.h index 82f4236b..69140566 100644 --- a/sigc++/visit_each.h +++ b/sigc++/visit_each.h @@ -1,5 +1,4 @@ -/* - * Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -12,95 +11,55 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * License along with this library; if not, see . */ -#ifndef _SIGC_VISIT_EACH_HPP_ -#define _SIGC_VISIT_EACH_HPP_ +#ifndef SIGC_VISIT_EACH_HPP +#define SIGC_VISIT_EACH_HPP #include #include +#include // std::forward +#include -namespace sigc { - -#ifndef DOXYGEN_SHOULD_SKIP_THIS -namespace internal { - -//This should really be an inner class of limit_derived_target, without the T_limit template type, -//But the SUN CC 5.7 (not earlier versions) compiler finds it ambiguous when we specify a particular specialization of it. -//and does not seem to allow us to tell it explicitly that it's an inner class. -template -struct with_type; - -//Specialization for I_derived = false -template struct -with_type -{ - static void execute_(const T_type&, const T_limit&) {} -}; - -//Specialization for I_derived = true -template -struct with_type -{ - static void execute_(const T_type& _A_type, const T_limit& _A_action) - { _A_action.action_(_A_type); } -}; - - -/// Helper struct for visit_each_type(). -template -struct limit_derived_target +namespace sigc { - typedef limit_derived_target T_self; - - template - void operator()(const T_type& _A_type) const - { - with_type::value || std::is_same::value, T_type, T_self>::execute_(_A_type, *this); - } - - limit_derived_target(const T_action& _A_action) - : action_(_A_action) - {} - - T_action action_; -}; -// Specialization for T_target pointer types, to provide a slightly different execute_() implementation. +struct trackable; -template -struct with_type_pointer; - -//Specialization for I_derived = false -template -struct with_type_pointer +#ifndef DOXYGEN_SHOULD_SKIP_THIS +namespace internal { - static void execute_(const T_type&, const T_limit&) {} -}; -//Specialization for I_derived = true -template -struct with_type_pointer -{ - static void execute_(const T_type& _A_type, const T_limit& _A_action) - { _A_action.action_(&_A_type); } -}; +template +constexpr bool is_base_of_or_same_v = + std::is_base_of, std::decay_t>::value || + std::is_same, std::decay_t>::value; -template -struct limit_derived_target +/// Helper struct for visit_each_trackable(). +template +struct limit_trackable_target { - typedef limit_derived_target T_self; - - template - void operator()(const T_type& _A_type) const + template + void operator()(T_type&& type) const { - with_type_pointer::value || std::is_same::value, T_type, T_self>::execute_(_A_type, *this); + // Only call action_() if T_Type derives from trackable. + if constexpr (is_base_of_or_same_v) + { + std::invoke(action_, type); + } + else + { + // Prevent 'unreferenced formal parameter' warning from MSVC by 'using' type + static_cast(type); + } } - limit_derived_target(const T_action& _A_action) - : action_(_A_action) - {} + explicit limit_trackable_target(const T_action& action) : action_(action) {} + + limit_trackable_target(const limit_trackable_target& src) = delete; + limit_trackable_target& operator=(const limit_trackable_target& src) = delete; + limit_trackable_target(limit_trackable_target&& src) = delete; + limit_trackable_target& operator=(limit_trackable_target&& src) = delete; T_action action_; }; @@ -115,8 +74,9 @@ struct limit_derived_target // (argument-dependent lookup), and therefore there is no risk that a visit_each() overload // in e.g. Boost is selected by mistake. -/** sigc::visitor::do_visit_each() performs a functor on each of the targets of a functor. - * All unknown types just call @a _A_action on them. +/** sigc::visitor::do_visit_each() performs a functor on each of the targets of a + * functor. + * All unknown types just call @a action on them. * Add specializations that specialize the @a T_functor argument for your own * functor types, so that subobjects get visited. This is needed to enable * auto-disconnection support for your functor types. @@ -138,12 +98,12 @@ struct limit_derived_target * template <> * struct visitor * { - * template - * static void do_visit_each(const T_action& _A_action, - * const some_ns::some_functor& _A_target) + * template + * static void do_visit_each(const T_action& action, + * const some_ns::some_functor& target) * { - * sigc::visit_each(_A_action, _A_target.some_data_member); - * sigc::visit_each(_A_action, _A_target.some_other_functor); + * sigc::visit_each(action, target.some_data_member); + * sigc::visit_each(action, target.some_other_functor); * } * }; * } @@ -151,13 +111,13 @@ struct limit_derived_target * * @ingroup sigcfunctors */ -template +template struct visitor { - template - static void do_visit_each(const T_action& _A_action, const T_functor& _A_functor) + template + static void do_visit_each(const T_action& action, const T_functor& functor) { - _A_action(_A_functor); + action(functor); } }; @@ -165,41 +125,35 @@ struct visitor * * @ingroup sigcfunctors */ -template -void visit_each(const T_action& _A_action, const T_functor& _A_functor) -{ sigc::visitor::do_visit_each(_A_action, _A_functor); } +template +void +visit_each(const T_action& action, const T_functor& functor) +{ + sigc::visitor::do_visit_each(action, functor); +} /** This function performs a functor on each of the targets * of a functor limited to a restricted type. * + * It is currently used only to call slot_do_bind and slot_do_unbind + * only on trackable-derived arguments of the functors, like a compile-time version of + * if(dynamic_cast parameters + * in the visitor template specialization. + * TODO: Remove the need for slot_do_bind/slot_do_unbind, limit_trackable_target, + * and visit_each_trackable() by just using a constexpr_if + * (previously known as static_if) if that ends up in C++17. + * * @ingroup sigcfunctors */ -template -void visit_each_type(const T_action& _A_action, const T_functor& _A_functor) +template +void +visit_each_trackable(const T_action& action, const T_functor& functor) { - typedef internal::limit_derived_target type_limited_action; - - type_limited_action limited_action(_A_action); - - //specifying the types of the template specialization prevents disconnection of bound trackable references (such as with sigc::ref()), - //probably because the visit_each<> specializations take various different template types, - //in various sequences, and we are probably specifying only a subset of them with this. - // - //But this is required by the AIX (and maybe IRIX MipsPro and Tru64) compilers. - //I guess that sigc::ref() therefore does not work on those platforms. murrayc - // sigc::visit_each(limited_action, _A_functor); - - //g++ (even slightly old ones) is our primary platform, so we could use the non-crashing version. - //However, the explicit version also fixes a crash in a slightly more common case: http://bugzilla.gnome.org/show_bug.cgi?id=169225 - //Users (and distributors) of libsigc++ on AIX (and maybe IRIX MipsPro and Tru64) do - //need to use the version above instead, to allow compilation. - - //Added 2014-03-20: The preceding comment probably does not apply any more, - //now when the visit_each<>() overloads have been replaced by visitor<> specializations. - //It's probably safe to add explicit template parameters on calls to visit_each(), - //visit_each_type() and visitor::do_visit_each(), if necessary. + internal::limit_trackable_target limited_action(action); - sigc::visit_each(limited_action, _A_functor); + sigc::visit_each(limited_action, functor); } } /* namespace sigc */ diff --git a/sigc++/weak_raw_ptr.h b/sigc++/weak_raw_ptr.h new file mode 100644 index 00000000..1830066a --- /dev/null +++ b/sigc++/weak_raw_ptr.h @@ -0,0 +1,101 @@ +/* Copyright 2016, The libsigc++ Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef SIGC_WEAK_RAW_PTR_HPP +#define SIGC_WEAK_RAW_PTR_HPP +#include //Just for notifiable. + +namespace sigc +{ + +struct notifiable; + +namespace internal +{ + +/** T must derive from sigc::trackable. + */ +template +struct weak_raw_ptr : public sigc::notifiable +{ + inline weak_raw_ptr() : p_(nullptr) {} + + inline weak_raw_ptr(T* p) noexcept : p_(p) + { + if (!p) + return; + + p->add_destroy_notify_callback(this, ¬ify_object_invalidated); + } + + inline weak_raw_ptr(const weak_raw_ptr& src) noexcept : p_(src.p_) + { + if (p_) + p_->add_destroy_notify_callback(this, ¬ify_object_invalidated); + } + + inline weak_raw_ptr& operator=(const weak_raw_ptr& src) noexcept + { + if (p_) + { + p_->remove_destroy_notify_callback(this); + } + + p_ = src.p_; + + if (p_) + p_->add_destroy_notify_callback(this, ¬ify_object_invalidated); + + return *this; + } + + // TODO: + weak_raw_ptr(weak_raw_ptr&& src) = delete; + weak_raw_ptr& operator=(weak_raw_ptr&& src) = delete; + + inline ~weak_raw_ptr() noexcept + { + if (p_) + { + p_->remove_destroy_notify_callback(this); + } + } + + inline explicit operator bool() const noexcept { return p_ != nullptr; } + + inline T* operator->() const noexcept { return p_; } + +private: + /** Callback that is executed when the objet is destroyed. + * @param data The object notified (@p this). + */ + static void notify_object_invalidated(notifiable* data) + { + auto self = static_cast(data); + if (!self) + return; + + self->p_ = nullptr; + } + + T* p_; +}; + +} /* namespace internal */ + +} /* namespace sigc */ + +#endif /* SIGC_WEAK_RAW_PTR_HPP */ diff --git a/sigc++config.h.cmake b/sigc++config.h.cmake new file mode 100644 index 00000000..8483ad35 --- /dev/null +++ b/sigc++config.h.cmake @@ -0,0 +1,63 @@ + +/* Define to omit deprecated API from the library. */ +#cmakedefine SIGCXX_DISABLE_DEPRECATED + +/* Major version number of sigc++. */ +#cmakedefine SIGCXX_MAJOR_VERSION @SIGCXX_MAJOR_VERSION@ + +/* Micro version number of sigc++. */ +#cmakedefine SIGCXX_MICRO_VERSION @SIGCXX_MICRO_VERSION@ + +/* Minor version number of sigc++. */ +#cmakedefine SIGCXX_MINOR_VERSION @SIGCXX_MINOR_VERSION@ + +/* Detect Win32 platform */ +#ifdef _WIN32 +# if defined(_MSC_VER) +# define SIGC_MSC 1 +# define SIGC_WIN32 1 +# ifndef LIBSIGCXX_STATIC +# define SIGC_DLL 1 +# endif +# elif defined(__CYGWIN__) +# define SIGC_CONFIGURE 1 +# elif defined(__MINGW32__) +# define SIGC_WIN32 1 +# define SIGC_CONFIGURE 1 +# else +# error "libsigc++ config: Unknown win32 architecture (send me gcc --dumpspecs or equiv)" +# endif +#else /* !_WIN32 */ +# define SIGC_CONFIGURE 1 +#endif /* !_WIN32 */ + +#ifdef SIGC_MSC +/* + * Visual C++ Warning C4251 says that the classes to any member objects in an + * exported class must also be exported. Some of the libsigc++ + * template classes contain std::list members. MS KB article 168958 says + * that it's not possible to export a std::list instantiation due to some + * wacky class nesting issues, so our only options are to ignore the + * warning or to modify libsigc++ to remove the std::list dependency. + * AFAICT, the std::list members are used internally by the library code + * and don't need to be used from the outside, and ignoring the warning + * seems to have no adverse effects, so that seems like a good enough + * solution for now. + */ +# pragma warning(disable:4251) + +#else /* SIGC_MSC */ + +#endif /* !SIGC_MSC */ + +#ifdef SIGC_DLL +# ifdef SIGC_BUILD +# define SIGC_API __declspec(dllexport) +# elif !defined(SIGC_BUILD) +# define SIGC_API __declspec(dllimport) +# else +# define SIGC_API +# endif +#else /* !SIGC_DLL */ +# define SIGC_API +#endif /* !SIGC_DLL */ diff --git a/sigc++config.h.in b/sigc++config.h.in index 22228556..2031e517 100644 --- a/sigc++config.h.in +++ b/sigc++config.h.in @@ -13,25 +13,27 @@ /* Detect Win32 platform */ #ifdef _WIN32 -# if defined(_MSC_VER) -# define SIGC_MSC 1 -# define SIGC_WIN32 1 -# define SIGC_DLL 1 -# elif defined(__CYGWIN__) -# define SIGC_CONFIGURE 1 -# elif defined(__MINGW32__) -# define SIGC_WIN32 1 -# define SIGC_CONFIGURE 1 -# else -# error "libsigc++ config: Unknown win32 architecture (send me gcc --dumpspecs or equiv)" -# endif +#if defined(_MSC_VER) +#define SIGC_MSC 1 +#define SIGC_WIN32 1 +#ifndef LIBSIGCXX_STATIC +#define SIGC_DLL 1 +#endif +#elif defined(__CYGWIN__) +#define SIGC_CONFIGURE 1 +#elif defined(__MINGW32__) +#define SIGC_WIN32 1 +#define SIGC_CONFIGURE 1 +#else +#error "libsigc++ config: Unknown win32 architecture (send me gcc --dumpspecs or equiv)" +#endif #else /* !_WIN32 */ -# define SIGC_CONFIGURE 1 +#define SIGC_CONFIGURE 1 #endif /* !_WIN32 */ #ifdef SIGC_MSC /* - * MS VC7 Warning 4251 says that the classes to any member objects in an + * Visual C++ Warning C4251 says that the classes to any member objects in an * exported class must also be exported. Some of the libsigc++ * template classes contain std::list members. MS KB article 168958 says * that it's not possible to export a std::list instantiation due to some @@ -42,43 +44,20 @@ * seems to have no adverse effects, so that seems like a good enough * solution for now. */ -# pragma warning(disable:4251) - -# define SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD 1 -# define SIGC_NEW_DELETE_IN_LIBRARY_ONLY 1 /* To keep ABI compatibility */ -# define SIGC_PRAGMA_PUSH_POP_MACRO 1 - -#if (_MSC_VER < 1900) && !defined (noexcept) -#define _ALLOW_KEYWORD_MACROS 1 -#define noexcept _NOEXCEPT -#endif +#pragma warning(disable : 4251) #else /* SIGC_MSC */ -/* does the C++ compiler support the use of a particular specialization when - calling operator() template methods. */ -# undef SIGC_GCC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - -/* Define if the non-standard Sun reverse_iterator must be used. */ -# undef SIGC_HAVE_SUN_REVERSE_ITERATOR - -/* does the C++ compiler support the use of a particular specialization when - calling operator() template methods omitting the template keyword. */ -# undef SIGC_MSVC_TEMPLATE_SPECIALIZATION_OPERATOR_OVERLOAD - -/* does the C++ preprocessor support pragma push_macro() and pop_macro(). */ -# undef SIGC_PRAGMA_PUSH_POP_MACRO - #endif /* !SIGC_MSC */ #ifdef SIGC_DLL -# if defined(SIGC_BUILD) && defined(_WINDLL) -# define SIGC_API __declspec(dllexport) -# elif !defined(SIGC_BUILD) -# define SIGC_API __declspec(dllimport) -# else -# define SIGC_API -# endif +#ifdef SIGC_BUILD +#define SIGC_API __declspec(dllexport) +#elif !defined(SIGC_BUILD) +#define SIGC_API __declspec(dllimport) +#else +#define SIGC_API +#endif #else /* !SIGC_DLL */ -# define SIGC_API +#define SIGC_API #endif /* !SIGC_DLL */ diff --git a/sigc++config.h.meson b/sigc++config.h.meson new file mode 100644 index 00000000..7fe4e765 --- /dev/null +++ b/sigc++config.h.meson @@ -0,0 +1,68 @@ +/* This file is part of libsigc++. */ +#ifndef SIGCXXCONFIG_H_INCLUDED +#define SIGCXXCONFIG_H_INCLUDED + +/* Define to omit deprecated API from the library. */ +#mesondefine SIGCXX_DISABLE_DEPRECATED + +/* Major version number of sigc++. */ +#mesondefine SIGCXX_MAJOR_VERSION + +/* Minor version number of sigc++. */ +#mesondefine SIGCXX_MINOR_VERSION + +/* Micro version number of sigc++. */ +#mesondefine SIGCXX_MICRO_VERSION + +/* Detect Win32 platform */ +#ifdef _WIN32 +#if defined(_MSC_VER) +#define SIGC_MSC 1 +#define SIGC_WIN32 1 +#ifndef LIBSIGCXX_STATIC +#define SIGC_DLL 1 +#endif +#elif defined(__CYGWIN__) +#define SIGC_CONFIGURE 1 +#elif defined(__MINGW32__) +#define SIGC_WIN32 1 +#define SIGC_CONFIGURE 1 +#else +#error "libsigc++ config: Unknown win32 architecture (send me gcc --dumpspecs or equiv)" +#endif +#else /* !_WIN32 */ +#define SIGC_CONFIGURE 1 +#endif /* !_WIN32 */ + +#ifdef SIGC_MSC +/* + * Visual C++ Warning C4251 says that the classes to any member objects in an + * exported class must also be exported. Some of the libsigc++ + * template classes contain std::list members. MS KB article 168958 says + * that it's not possible to export a std::list instantiation due to some + * wacky class nesting issues, so our only options are to ignore the + * warning or to modify libsigc++ to remove the std::list dependency. + * AFAICT, the std::list members are used internally by the library code + * and don't need to be used from the outside, and ignoring the warning + * seems to have no adverse effects, so that seems like a good enough + * solution for now. + */ +#pragma warning(disable : 4251) + +#else /* SIGC_MSC */ + +#endif /* !SIGC_MSC */ + +#ifdef SIGC_DLL +#ifdef SIGC_BUILD +#define SIGC_API __declspec(dllexport) +#elif !defined(SIGC_BUILD) +#define SIGC_API __declspec(dllimport) +#else +#define SIGC_API +#endif +#else /* !SIGC_DLL */ +#define SIGC_API +#endif /* !SIGC_DLL */ + +#endif /* !SIGCXXCONFIG_H_INCLUDED */ diff --git a/subprojects/mm-common.wrap b/subprojects/mm-common.wrap new file mode 100644 index 00000000..296109fa --- /dev/null +++ b/subprojects/mm-common.wrap @@ -0,0 +1,9 @@ +[wrap-git] +directory=mm-common +url=https://gitlab.gnome.org/GNOME/mm-common.git +revision=master +depth=1 + +[provide] +dependency_names = mm-common-libstdc++ +program_names = mm-common-get diff --git a/tests/.gitignore b/tests/.gitignore index be803fcb..0a788ab4 100644 --- a/tests/.gitignore +++ b/tests/.gitignore @@ -3,10 +3,12 @@ /test_accumulated /test_accum_iter /test_bind +/test_bind_as_slot /test_bind_ref /test_bind_refptr /test_bind_return /test_compose +/test_connection /test_copy_invalid_slot /test_cpp11_lambda /test_custom @@ -18,9 +20,11 @@ /test_hide /test_limit_reference /test_mem_fun +/test_member_method_trait /test_ptr_fun /test_retype /test_retype_return +/test_rvalue_ref /test_signal /test_signal_move /test_size @@ -30,4 +34,13 @@ /test_trackable /test_trackable_move /test_track_obj +/test_tuple_cat +/test_tuple_cdr +/test_tuple_end +/test_tuple_for_each +/test_tuple_start +/test_tuple_transform_each /test_visit_each +/test_visit_each_trackable +/test_weak_raw_ptr +/benchmark diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt new file mode 100644 index 00000000..4fcbc59c --- /dev/null +++ b/tests/CMakeLists.txt @@ -0,0 +1,77 @@ +# Copyright 2016, The libsigc++ Development Team +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, see . + +enable_testing () + +set (TEST_SOURCE_FILES + test_accum_iter.cc + test_accumulated.cc + test_bind_as_slot.cc + test_bind.cc + test_bind_ref.cc + test_bind_refptr.cc + test_bind_return.cc + test_compose.cc + test_connection.cc + test_copy_invalid_slot.cc + test_cpp11_lambda.cc + test_custom.cc + test_disconnect.cc + test_disconnect_during_emit.cc + test_exception_catch.cc + test_hide.cc + test_limit_reference.cc + test_member_method_trait.cc + test_mem_fun.cc + test_ptr_fun.cc + test_retype.cc + test_retype_return.cc + test_rvalue_ref.cc + test_scoped_connection.cc + test_signal.cc + test_signal_connect.cc + test_signal_move.cc + test_size.cc + test_slot.cc + test_slot_disconnect.cc + test_slot_move.cc + test_trackable.cc + test_trackable_move.cc + test_track_obj.cc + test_tuple_cdr.cc + test_tuple_end.cc + test_tuple_for_each.cc + test_tuple_start.cc + test_tuple_transform_each.cc + test_visit_each.cc + test_visit_each_trackable.cc + test_weak_raw_ptr.cc) + +function (add_sigcpp_test TEST_SOURCE_FILE) + get_filename_component (test_name ${TEST_SOURCE_FILE} NAME_WE) + add_executable (${test_name} ${TEST_SOURCE_FILE} testutilities.cc) + target_link_libraries (${test_name} sigc-${SIGCXX_API_VERSION}) + add_test (NAME ${test_name} + # Help MSVC to find the library that the tests should link against. + COMMAND ${CMAKE_COMMAND} -E env "PATH=$;$ENV{PATH}" $) + + if (MSVC AND test_name MATCHES "^(test_retype_return|test_signal)$") + target_compile_options(${test_name} PRIVATE "/wd4244") + endif() +endfunction (add_sigcpp_test) + +foreach (test_file ${TEST_SOURCE_FILES}) + add_sigcpp_test (${test_file}) +endforeach() diff --git a/tests/Makefile.am b/tests/Makefile.am index f175f32b..c34f0020 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -17,7 +17,11 @@ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) AM_CXXFLAGS = $(SIGC_WXXFLAGS) -LDADD = $(top_builddir)/sigc++/libsigc-$(SIGCXX_API_VERSION).la + +sigc_libs = $(top_builddir)/sigc++/libsigc-$(SIGCXX_API_VERSION).la +LDADD = $(sigc_libs) + +dist_noinst_DATA = CMakeLists.txt check_PROGRAMS = \ test_accum_iter \ @@ -28,21 +32,24 @@ check_PROGRAMS = \ test_bind_refptr \ test_bind_return \ test_compose \ + test_connection \ test_copy_invalid_slot \ test_cpp11_lambda \ test_custom \ - test_deduce_result_type \ test_disconnect \ test_disconnect_during_emit \ test_exception_catch \ - test_functor_trait \ test_hide \ test_limit_reference \ + test_member_method_trait \ test_mem_fun \ test_ptr_fun \ test_retype \ test_retype_return \ + test_rvalue_ref \ + test_scoped_connection \ test_signal \ + test_signal_connect \ test_signal_move \ test_size \ test_slot \ @@ -51,7 +58,14 @@ check_PROGRAMS = \ test_trackable \ test_trackable_move \ test_track_obj \ - test_visit_each + test_tuple_cdr \ + test_tuple_end \ + test_tuple_for_each \ + test_tuple_start \ + test_tuple_transform_each \ + test_visit_each \ + test_visit_each_trackable \ + test_weak_raw_ptr TESTS = $(check_PROGRAMS) @@ -65,21 +79,24 @@ test_bind_ref_SOURCES = test_bind_ref.cc $(sigc_test_util) test_bind_refptr_SOURCES = test_bind_refptr.cc $(sigc_test_util) test_bind_return_SOURCES = test_bind_return.cc $(sigc_test_util) test_compose_SOURCES = test_compose.cc $(sigc_test_util) +test_connection_SOURCES = test_connection.cc $(sigc_test_util) test_copy_invalid_slot_SOURCES = test_copy_invalid_slot.cc $(sigc_test_util) test_cpp11_lambda_SOURCES = test_cpp11_lambda.cc $(sigc_test_util) test_custom_SOURCES = test_custom.cc $(sigc_test_util) -test_deduce_result_type_SOURCES = test_deduce_result_type.cc $(sigc_test_util) test_disconnect_SOURCES = test_disconnect.cc $(sigc_test_util) test_disconnect_during_emit_SOURCES = test_disconnect_during_emit.cc $(sigc_test_util) test_exception_catch_SOURCES = test_exception_catch.cc $(sigc_test_util) -test_functor_trait_SOURCES = test_functor_trait.cc $(sigc_test_util) test_hide_SOURCES = test_hide.cc $(sigc_test_util) test_limit_reference_SOURCES = test_limit_reference.cc $(sigc_test_util) +test_member_method_trait_SOURCES = test_member_method_trait.cc $(sigc_test_util) test_mem_fun_SOURCES = test_mem_fun.cc $(sigc_test_util) test_ptr_fun_SOURCES = test_ptr_fun.cc $(sigc_test_util) test_retype_SOURCES = test_retype.cc $(sigc_test_util) test_retype_return_SOURCES = test_retype_return.cc $(sigc_test_util) +test_rvalue_ref_SOURCES = test_rvalue_ref.cc $(sigc_test_util) +test_scoped_connection_SOURCES = test_scoped_connection.cc $(sigc_test_util) test_signal_SOURCES = test_signal.cc $(sigc_test_util) +test_signal_connect_SOURCES = test_signal_connect.cc $(sigc_test_util) test_signal_move_SOURCES = test_signal_move.cc $(sigc_test_util) test_size_SOURCES = test_size.cc $(sigc_test_util) test_slot_SOURCES = test_slot.cc $(sigc_test_util) @@ -88,4 +105,19 @@ test_slot_move_SOURCES = test_slot_move.cc $(sigc_test_util) test_trackable_SOURCES = test_trackable.cc $(sigc_test_util) test_trackable_move_SOURCES = test_trackable_move.cc $(sigc_test_util) test_track_obj_SOURCES = test_track_obj.cc $(sigc_test_util) +test_tuple_cdr_SOURCES = test_tuple_cdr.cc $(sigc_test_util) +test_tuple_end_SOURCES = test_tuple_end.cc $(sigc_test_util) +test_tuple_for_each_SOURCES = test_tuple_for_each.cc $(sigc_test_util) +test_tuple_start_SOURCES = test_tuple_start.cc $(sigc_test_util) +test_tuple_transform_each_SOURCES = test_tuple_transform_each.cc $(sigc_test_util) test_visit_each_SOURCES = test_visit_each.cc $(sigc_test_util) +test_visit_each_trackable_SOURCES = test_visit_each_trackable.cc $(sigc_test_util) +test_weak_raw_ptr_SOURCES = test_weak_raw_ptr.cc $(sigc_test_util) + +if SIGC_BUILD_BENCHMARK +check_PROGRAMS += benchmark +benchmark_SOURCES = benchmark.cc $(sigc_test_util) +benchmark_LDADD = $(sigc_libs) \ + $(BOOST_SYSTEM_LIB) \ + $(BOOST_TIMER_LIB) +endif diff --git a/tests/benchmark.cc b/tests/benchmark.cc new file mode 100644 index 00000000..4f11df77 --- /dev/null +++ b/tests/benchmark.cc @@ -0,0 +1,120 @@ +/* Copyright 2003 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include +#include +#include +#include + +const int COUNT = 10000000; + +struct foo : public sigc::trackable +{ + int bar(int a); + int c; +}; + +int +foo::bar(int a) +{ + int b = c; + c = a; + return b; +} + +void +test_slot_call() +{ + foo foobar1; + + // slot benchmark ... + + sigc::slot slot = sigc::mem_fun(foobar1, &foo::bar); + + std::cout << "elapsed time for calling a slot " << COUNT << " times:" << std::endl; + boost::timer::auto_cpu_timer timer; + + for (int i = 0; i < COUNT; ++i) + slot(i); +} + +void +test_signal_emit() +{ + sigc::signal emitter; + + std::cout << "elapsed time for " << COUNT << " emissions (0 slots):" << std::endl; + boost::timer::auto_cpu_timer timer; + + for (int i = 0; i < COUNT; ++i) + emitter(i); +} + +void +test_connected_signal_emit() +{ + foo foobar1; + sigc::signal emitter; + emitter.connect(mem_fun(foobar1, &foo::bar)); + + std::cout << "elapsed time for " << COUNT << " emissions (1 slot):" << std::endl; + boost::timer::auto_cpu_timer timer; + + for (int i = 0; i < COUNT; ++i) + emitter(i); +} + +void +test_connected_multiple_signal_emit() +{ + foo foobar1, foobar2, foobar3, foobar4, foobar5; + + sigc::signal emitter; + emitter.connect(mem_fun(foobar2, &foo::bar)); + emitter.connect(mem_fun(foobar3, &foo::bar)); + emitter.connect(mem_fun(foobar4, &foo::bar)); + emitter.connect(mem_fun(foobar5, &foo::bar)); + + std::cout << "elapsed time for " << COUNT << " emissions (5 slots):" << std::endl; + boost::timer::auto_cpu_timer timer; + + for (int i = 0; i < COUNT; ++i) + emitter(i); +} + +void +test_connect_disconnect() +{ + foo foobar1; + sigc::signal emitter; + sigc::connection conn; + + std::cout << "elapsed time for " << COUNT << " connections/disconnections:" << std::endl; + boost::timer::auto_cpu_timer timer; + + for (int i = 0; i < COUNT; ++i) + { + conn = emitter.connect(mem_fun(foobar1, &foo::bar)); + conn.disconnect(); + } +} + +int +main() +{ + // slot benchmark ... + test_slot_call(); + + // emission benchmark (zero slots) ... + test_signal_emit(); + + // emission benchmark (one slot) ... + test_connected_signal_emit(); + + // emission benchmark (five slot) ... + test_connected_multiple_signal_emit(); + + // connection / disconnection benchmark ... + test_connect_disconnect(); +} diff --git a/tests/memleakcheck.sh b/tests/memleakcheck.sh new file mode 100755 index 00000000..38fbd586 --- /dev/null +++ b/tests/memleakcheck.sh @@ -0,0 +1,23 @@ +#!/bin/bash + +# Run all libsigc++ tests with valgrind, searching for memory leaks. +# Execute this script in the tests directory. +# valgrind --leak-check=full .libs/lt-test_* + +for testprog in test_accum_iter test_accumulated test_bind test_bind_as_slot \ + test_bind_ref test_bind_refptr test_bind_return test_compose test_connection \ + test_copy_invalid_slot test_cpp11_lambda test_custom test_disconnect \ + test_disconnect_during_emit test_exception_catch test_hide \ + test_limit_reference test_member_method_trait test_mem_fun test_ptr_fun \ + test_retype test_retype_return test_rvalue_ref test_signal test_signal_move \ + test_size test_slot test_slot_disconnect test_slot_move test_trackable \ + test_trackable_move test_track_obj test_tuple_cdr test_tuple_end \ + test_tuple_for_each test_tuple_start test_tuple_transform_each \ + test_visit_each test_visit_each_trackable test_weak_raw_ptr +do + echo ================ + echo === $testprog + echo ================ + valgrind --leak-check=full .libs/lt-$testprog +done + diff --git a/tests/meson.build b/tests/meson.build new file mode 100644 index 00000000..4b627e94 --- /dev/null +++ b/tests/meson.build @@ -0,0 +1,107 @@ +# tests + +# input: sigcxx_own_dep, build_tests, do_benchmark, can_benchmark, benchmark_dep + +benchmark_timeout = 100 + +test_programs = [ +# [[dir-name], exe-name, [sources]] + [[], 'test_accum_iter', ['test_accum_iter.cc', 'testutilities.cc']], + [[], 'test_accumulated', ['test_accumulated.cc', 'testutilities.cc']], + [[], 'test_bind', ['test_bind.cc', 'testutilities.cc']], + [[], 'test_bind_as_slot', ['test_bind_as_slot.cc', 'testutilities.cc']], + [[], 'test_bind_ref', ['test_bind_ref.cc', 'testutilities.cc']], + [[], 'test_bind_refptr', ['test_bind_refptr.cc', 'testutilities.cc']], + [[], 'test_bind_return', ['test_bind_return.cc', 'testutilities.cc']], + [[], 'test_compose', ['test_compose.cc', 'testutilities.cc']], + [[], 'test_connection', ['test_connection.cc', 'testutilities.cc']], + [[], 'test_copy_invalid_slot', ['test_copy_invalid_slot.cc', 'testutilities.cc']], + [[], 'test_cpp11_lambda', ['test_cpp11_lambda.cc', 'testutilities.cc']], + [[], 'test_custom', ['test_custom.cc', 'testutilities.cc']], + [[], 'test_disconnect', ['test_disconnect.cc', 'testutilities.cc']], + [[], 'test_disconnect_during_emit', ['test_disconnect_during_emit.cc', 'testutilities.cc']], + [[], 'test_exception_catch', ['test_exception_catch.cc', 'testutilities.cc']], + [[], 'test_hide', ['test_hide.cc', 'testutilities.cc']], + [[], 'test_limit_reference', ['test_limit_reference.cc', 'testutilities.cc']], + [[], 'test_member_method_trait', ['test_member_method_trait.cc', 'testutilities.cc']], + [[], 'test_mem_fun', ['test_mem_fun.cc', 'testutilities.cc']], + [[], 'test_ptr_fun', ['test_ptr_fun.cc', 'testutilities.cc']], + [[], 'test_retype', ['test_retype.cc', 'testutilities.cc']], + [[], 'test_retype_return', ['test_retype_return.cc', 'testutilities.cc']], + [[], 'test_rvalue_ref', ['test_rvalue_ref.cc', 'testutilities.cc']], + [[], 'test_scoped_connection', ['test_scoped_connection.cc', 'testutilities.cc']], + [[], 'test_signal', ['test_signal.cc', 'testutilities.cc']], + [[], 'test_signal_connect', ['test_signal_connect.cc', 'testutilities.cc']], + [[], 'test_signal_move', ['test_signal_move.cc', 'testutilities.cc']], + [[], 'test_size', ['test_size.cc', 'testutilities.cc']], + [[], 'test_slot', ['test_slot.cc', 'testutilities.cc']], + [[], 'test_slot_disconnect', ['test_slot_disconnect.cc', 'testutilities.cc']], + [[], 'test_slot_move', ['test_slot_move.cc', 'testutilities.cc']], + [[], 'test_trackable', ['test_trackable.cc', 'testutilities.cc']], + [[], 'test_trackable_move', ['test_trackable_move.cc', 'testutilities.cc']], + [[], 'test_track_obj', ['test_track_obj.cc', 'testutilities.cc']], + [[], 'test_tuple_cdr', ['test_tuple_cdr.cc', 'testutilities.cc']], + [[], 'test_tuple_end', ['test_tuple_end.cc', 'testutilities.cc']], + [[], 'test_tuple_for_each', ['test_tuple_for_each.cc', 'testutilities.cc']], + [[], 'test_tuple_start', ['test_tuple_start.cc', 'testutilities.cc']], + [[], 'test_tuple_transform_each', ['test_tuple_transform_each.cc', 'testutilities.cc']], + [[], 'test_visit_each', ['test_visit_each.cc', 'testutilities.cc']], + [[], 'test_visit_each_trackable', ['test_visit_each_trackable.cc', 'testutilities.cc']], + [[], 'test_weak_raw_ptr', ['test_weak_raw_ptr.cc', 'testutilities.cc']], +] + +benchmark_programs = [ +# [[dir-name], exe-name, [sources]] + [[], 'benchmark1', ['benchmark.cc']], +] + +foreach ex : test_programs + dir = '' + foreach dir_part : ex[0] + dir = dir / dir_part + endforeach + ex_name = (dir / ex[1]).underscorify() + ex_sources = [] + foreach src : ex[2] + ex_sources += dir / src + endforeach + + exe_file = executable(ex_name, ex_sources, + dependencies: sigcxx_own_dep, + implicit_include_directories: false, + build_by_default: build_tests, + install: false, + ) + + # If exe_file is a test program, it is built by default unconditionally. + if build_tests + test(ex_name, exe_file) + endif +endforeach + +if can_benchmark + foreach ex : benchmark_programs + dir = '' + foreach dir_part : ex[0] + dir = dir / dir_part + endforeach + ex_name = (dir / ex[1]).underscorify() + ex_sources = [] + foreach src : ex[2] + ex_sources += dir / src + endforeach + + exe_file = executable(ex_name, ex_sources, + dependencies: [sigcxx_own_dep, benchmark_dep], + implicit_include_directories: false, + build_by_default: do_benchmark, + install: false, + ) + + if do_benchmark + test(ex_name, exe_file, + timeout: benchmark_timeout, + ) + endif + endforeach +endif diff --git a/tests/test_accum_iter.cc b/tests/test_accum_iter.cc index 486fa27e..10f70e18 100644 --- a/tests/test_accum_iter.cc +++ b/tests/test_accum_iter.cc @@ -1,15 +1,17 @@ +/* Copyright 2007 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + #include "testutilities.h" #include -#include #include -#include -#include namespace { std::ostringstream result_stream; -int ident(int i) +int +ident(int i) { return i; } @@ -17,14 +19,8 @@ int ident(int i) template struct min_accum { - typedef T result_type; - - template -#ifndef SIGC_HAVE_SUN_REVERSE_ITERATOR - typename std::iterator_traits::value_type operator()(I i1, I i2) -#else - typename I::value_type operator()(I i1, I i2) -#endif + template + decltype(auto) operator()(I i1, I i2) { return *std::min_element(i1, i2); } @@ -32,14 +28,15 @@ struct min_accum } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::signal0 > signal; + sigc::signal::accumulated> signal; signal.connect(sigc::bind(sigc::ptr_fun(ident), 3)); signal.connect(sigc::bind(sigc::ptr_fun(ident), 1)); diff --git a/tests/test_accumulated.cc b/tests/test_accumulated.cc index adbc2956..7fa81cc9 100644 --- a/tests/test_accumulated.cc +++ b/tests/test_accumulated.cc @@ -1,25 +1,21 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include -#include #include #include -#include namespace { + +TestUtilities* util = nullptr; std::ostringstream result_stream; struct arithmetic_mean_accumulator { - typedef double result_type; template double operator()(T_iterator first, T_iterator last) const { @@ -31,28 +27,29 @@ struct arithmetic_mean_accumulator } }; -template +template struct vector_accumulator { - typedef std::vector result_type; template - result_type operator()(T_iterator first, T_iterator last) const + std::vector operator()(T_iterator first, T_iterator last) const { - result_type vec; + std::vector vec; for (; first != last; ++first) vec.push_back(*first); return vec; } }; -int foo(int i) +int +foo(int i) { const int result = 3 * i + 1; result_stream << "foo: " << result << ", "; return result; } -int bar(double i) +int +bar(double i) { const int result = 5 * int(i) - 3; result_stream << "bar: " << result << ", "; @@ -69,58 +66,81 @@ struct A : public sigc::trackable } }; -} // end anonymous namespace - -int main(int argc, char* argv[]) +void +test_empty_signal() { - auto util = TestUtilities::get_instance(); - - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - - sigc::signal::accumulated sig; - sigc::signal::accumulated > sig_vec; + sigc::signal::accumulated sig; + sigc::signal::accumulated> sig_vec; result_stream << "Result (empty slot list): " << sig(0); util->check_result(result_stream, "Result (empty slot list): -1"); result_stream << "Vector result (empty slot list): " << (sig_vec(0).empty() ? "empty" : "not empty"); util->check_result(result_stream, "Vector result (empty slot list): empty"); +} - A a; - sig.connect(sigc::ptr_fun1(&foo)); - sig.connect(sigc::mem_fun1(&a, &A::foo)); - sig.connect(sigc::ptr_fun1(&bar)); +template +void +test_mean() +{ + typename T_signal::template accumulated sig; - sig_vec.connect(sigc::ptr_fun1(&foo)); - sig_vec.connect(sigc::mem_fun1(&a, &A::foo)); - sig_vec.connect(sigc::ptr_fun1(&bar)); + A a; + sig.connect(sigc::ptr_fun(&foo)); + sig.connect(sigc::mem_fun(a, &A::foo)); + sig.connect(sigc::ptr_fun(&bar)); double dres = sig(1); - result_stream << "Mean accumulator: Result (i=1): " - << std::fixed << std::setprecision(3) << dres; - util->check_result(result_stream, - "foo: 4, A::foo: 6, bar: 2, Mean accumulator: Result (i=1): 4.000"); + result_stream << "Mean accumulator: Result (i=1): " << std::fixed << std::setprecision(3) << dres; + util->check_result( + result_stream, "foo: 4, A::foo: 6, bar: 2, Mean accumulator: Result (i=1): 4.000"); dres = sig(11); - result_stream << "Mean accumulator: Plain Result (i=11): " - << std::fixed << std::setprecision(3) << dres; - util->check_result(result_stream, - "foo: 34, A::foo: 206, bar: 52, Mean accumulator: Plain Result (i=11): 97.333"); + result_stream << "Mean accumulator: Plain Result (i=11): " << std::fixed << std::setprecision(3) + << dres; + util->check_result( + result_stream, "foo: 34, A::foo: 206, bar: 52, Mean accumulator: Plain Result (i=11): 97.333"); +} + +void +test_vector_accumulator() +{ + sigc::signal::accumulated> sig_vec; + + A a; + sig_vec.connect(sigc::ptr_fun(&foo)); + sig_vec.connect(sigc::mem_fun(a, &A::foo)); + sig_vec.connect(sigc::ptr_fun(&bar)); auto res1 = sig_vec(1); result_stream << "Vector accumulator: Result (i=1): "; for (auto num : res1) result_stream << num << " "; - util->check_result(result_stream, - "foo: 4, A::foo: 6, bar: 2, Vector accumulator: Result (i=1): 4 6 2 "); + util->check_result( + result_stream, "foo: 4, A::foo: 6, bar: 2, Vector accumulator: Result (i=1): 4 6 2 "); auto res3 = sig_vec(3); result_stream << "Vector accumulator: Result (i=3): "; for (auto num : res3) result_stream << num << " "; - util->check_result(result_stream, - "foo: 10, A::foo: 46, bar: 12, Vector accumulator: Result (i=3): 10 46 12 "); + util->check_result( + result_stream, "foo: 10, A::foo: 46, bar: 12, Vector accumulator: Result (i=3): 10 46 12 "); +} + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_empty_signal(); + test_mean>(); + test_mean>(); + test_vector_accumulator(); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_bind.cc b/tests/test_bind.cc index 845d54c0..0cd192ca 100644 --- a/tests/test_bind.cc +++ b/tests/test_bind.cc @@ -1,33 +1,26 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include -#include namespace { std::ostringstream result_stream; -struct foo : public sigc::functor_base +struct foo { - // choose a type that can hold all return values - typedef int result_type; - int operator()(int i) { result_stream << "foo(int " << i << ") "; - return i > 0; + return static_cast(i > 0); } int operator()(int i, int j) { - result_stream << "foo(int " << i << ", int "<< j << ") "; + result_stream << "foo(int " << i << ", int " << j << ") "; return i + j; } @@ -38,49 +31,46 @@ struct foo : public sigc::functor_base } }; -struct foo_void : public sigc::functor_base +struct foo_void { - typedef void result_type; - - void operator()(int i) - { - result_stream << "foo_void(int " << i << ")"; - } + void operator()(int i) { result_stream << "foo_void(int " << i << ")"; } }; -int bar(int i, int j) +int +bar(int i, int j) { result_stream << "bar(int " << i << ", int " << j << ") "; return i + j; } -bool simple(bool test) +bool +simple(bool test) { result_stream << "simple(bool " << test << ") "; return test; } -void egon(std::string& str) +void +egon(std::string& str) { result_stream << "egon(string '" << str << "')"; str = "egon was here"; } - struct book : public sigc::trackable { - book(const std::string& name) : name_(name) {} + explicit book(const std::string& name) : name_(name) {} - //non-copyable: + // non-copyable: book(const book&) = delete; book& operator=(const book&) = delete; - - //non movable: + + // non movable: book(book&&) = delete; book& operator=(book&&) = delete; - std::string& get_name() { return name_; } - operator std::string& () { return get_name(); } + std::string& get_name() { return name_; } + operator std::string&() { return get_name(); } private: std::string name_; @@ -88,7 +78,8 @@ struct book : public sigc::trackable } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -130,7 +121,7 @@ int main(int argc, char* argv[]) // method pointer instead of functor book test_book("otto"); - result_stream << sigc::bind<0>(&book::get_name, sigc::ref(test_book))(); + result_stream << sigc::bind<0>(&book::get_name, std::ref(test_book))(); util->check_result(result_stream, "otto"); // test return type of bind_functor::operator() overload with no arguments @@ -142,25 +133,31 @@ int main(int argc, char* argv[]) // test references std::string str("guest book"); - sigc::bind(&egon, sigc::ref(str))(); // Tell bind that it shall store a reference. - result_stream << " " << str; // (This cannot be the default behaviour: just think about what happens if str dies!) + sigc::bind(&egon, std::ref(str))(); // Tell bind that it shall store a reference. + result_stream + << " " + << str; // (This cannot be the default behaviour: just think about what happens if str dies!) util->check_result(result_stream, "egon(string 'guest book') egon was here"); - sigc::slot sl; + sigc::slot sl; { + // Test without a positional template argument to std::bind(). book guest_book("karl"); - sl = sigc::bind(&egon, sigc::ref(guest_book)); + sl = sigc::bind(&egon, std::ref(guest_book)); sl(); result_stream << " " << static_cast(guest_book); util->check_result(result_stream, "egon(string 'karl') egon was here"); + + // Test with a positional template argument to std::bind<>(). + guest_book.get_name() = "ove"; + sl = sigc::bind<0>(&egon, std::ref(guest_book)); + sl(); + result_stream << " " << static_cast(guest_book); + util->check_result(result_stream, "egon(string 'ove') egon was here"); } // auto-disconnect sl(); util->check_result(result_stream, ""); - // This causes a crash when using g++ 3.3.4 or 3.3.5 (but not 3.4.x) when not specifying - // the exact template specialization in visit_each_type() - see the comments there. - // It looks like the auto-disconnect does not work, so the last sl() call tries - // to access the guest_book data again. return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_bind_as_slot.cc b/tests/test_bind_as_slot.cc index 28bcf4fd..4164fd90 100644 --- a/tests/test_bind_as_slot.cc +++ b/tests/test_bind_as_slot.cc @@ -1,34 +1,32 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include -#include //For std::ref(). -#include namespace { std::ostringstream result_stream; -bool func_to_bind(int a, int b) +bool +func_to_bind(int a, int b) { result_stream << "func_to_bind(" << a << ", " << b << ")"; return true; } -bool func_to_bind_with_iter(int a, std::string::iterator& b) +bool +func_to_bind_with_iter(int a, std::string::iterator& b) { result_stream << "func_to_bind_with_iter(" << a << ", " << *b << ")"; return true; } -bool func_to_bind_with_const_iter(int a, std::string::const_iterator& b) +bool +func_to_bind_with_const_iter(int a, std::string::const_iterator& b) { result_stream << "func_to_bind_with_const_iter(" << a << ", " << *b << ")"; return true; @@ -36,33 +34,35 @@ bool func_to_bind_with_const_iter(int a, std::string::const_iterator& b) } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - - //Test that sigc::bind()'s result can be converted to a sigc::slot<>. + // Test that sigc::bind()'s result can be converted to a sigc::slot<>. { - sigc::slot bound_slot = sigc::bind(sigc::ptr_fun(&func_to_bind), 2); + sigc::slot bound_slot = sigc::bind(sigc::ptr_fun(&func_to_bind), 2); bound_slot(1); util->check_result(result_stream, "func_to_bind(1, 2)"); } - //Test with a non-const iterator: + // Test with a non-const iterator: { std::string c = "2"; - sigc::slot bound_slot = sigc::bind(sigc::ptr_fun(&func_to_bind_with_iter), c.begin()); + sigc::slot bound_slot = + sigc::bind(sigc::ptr_fun(&func_to_bind_with_iter), c.begin()); bound_slot(1); util->check_result(result_stream, "func_to_bind_with_iter(1, 2)"); } - //Test with a const_iterator: + // Test with a const_iterator: { const std::string c = "2"; - sigc::slot bound_slot = sigc::bind(sigc::ptr_fun(&func_to_bind_with_const_iter), c.begin()); + sigc::slot bound_slot = + sigc::bind(sigc::ptr_fun(&func_to_bind_with_const_iter), c.begin()); bound_slot(1); util->check_result(result_stream, "func_to_bind_with_const_iter(1, 2)"); } diff --git a/tests/test_bind_ref.cc b/tests/test_bind_ref.cc index 58bd55da..33c0b9db 100644 --- a/tests/test_bind_ref.cc +++ b/tests/test_bind_ref.cc @@ -1,8 +1,9 @@ +/* Copyright 2005 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + #include "testutilities.h" #include -#include -#include -#include namespace { @@ -11,30 +12,30 @@ std::ostringstream result_stream; class Param : public sigc::trackable { public: - Param(const std::string& name) - : name_(name) - {} + explicit Param(const std::string& name) : name_(name) {} - //non-copyable, - //so it can only be used with sigc::bind() via sigc::ref() + // non-copyable, + // so it can only be used with sigc::bind() via sigc::ref() Param(const Param&) = delete; Param& operator=(const Param&) = delete; - //non movable: + // non movable: Param(Param&&) = delete; Param& operator=(Param&&) = delete; std::string name_; }; -void handler(Param& param) +void +handler(Param& param) { result_stream << " handler(param): param.name_=" << param.name_; } } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -42,32 +43,29 @@ int main(int argc, char* argv[]) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; auto slot_full = sigc::ptr_fun(&handler); - sigc::slot slot_bound; + sigc::slot slot_bound; slot_bound(); util->check_result(result_stream, ""); { - //Because Param derives from sigc::trackable(), sigc::ref() should disconnect + // Because Param derives from sigc::trackable(), std::ref() should disconnect // the signal handler when param is destroyed. Param param("murrayc"); // A convoluted way to do - // slot_bound = sigc::bind(slot_full, sigc::ref(param)); - slot_bound = sigc::bind< -1, sigc::reference_wrapper >(slot_full, sigc::ref(param)); + // slot_bound = sigc::bind(slot_full, std::ref(param)); + slot_bound = sigc::bind<-1, decltype(slot_full), std::reference_wrapper>( + slot_full, std::ref(param)); result_stream << "Calling slot when param exists:"; slot_bound(); - util->check_result(result_stream, - "Calling slot when param exists: handler(param): param.name_=murrayc"); + util->check_result( + result_stream, "Calling slot when param exists: handler(param): param.name_=murrayc"); } // auto-disconnect result_stream << "Calling slot when param does not exist:"; slot_bound(); util->check_result(result_stream, "Calling slot when param does not exist:"); - // This causes a crash when using g++ 3.3.4 or 3.3.5 (but not 3.4.x) when not specifying - // the exact template specialization in visit_each_type() - see the comments there. - // It looks like the auto-disconnect does not work, so the last slot_bound() call tries - // to access the param data again. return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_bind_refptr.cc b/tests/test_bind_refptr.cc index f8fe446a..dd75c4f9 100644 --- a/tests/test_bind_refptr.cc +++ b/tests/test_bind_refptr.cc @@ -1,3 +1,19 @@ +/* Copyright 2002 - 2016, The gtkmm Development Team + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + // Bug 564005 - Valgrind errors and crash on exit with Gtk::UIManager // Bug 154498 - Unnecessary warning on console: signalproxy_connectionnode.cc @@ -7,32 +23,12 @@ #include "testutilities.h" #include -#include -#include #define ACTIVATE_BUG 1 -// -*- c++ -*- #ifndef _GLIBMM_REFPTR_H #define _GLIBMM_REFPTR_H -/* Copyright 2002 The gtkmm Development Team - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - */ - //#include namespace Glib @@ -60,7 +56,7 @@ namespace Glib * See the "Memory Management" section in the "Programming with gtkmm" * book for further information. */ -template +template class RefPtr { public: @@ -86,8 +82,8 @@ class RefPtr * * Increments the reference count. */ - template - inline RefPtr(const RefPtr& src); + template + inline explicit RefPtr(const RefPtr& src); /** Swap the contents of two RefPtr<>. * This method swaps the internal pointers to T_CppObject. This can be @@ -103,7 +99,7 @@ class RefPtr * * Increments the reference count. */ - template + template inline RefPtr& operator=(const RefPtr& src); /// Tests whether the RefPtr<> point to the same underlying instance. @@ -130,9 +126,10 @@ class RefPtr inline explicit operator bool() const; #ifndef GLIBMM_DISABLE_DEPRECATED - /// @deprecated Use reset() instead because this leads to confusion with clear() methods on the underlying class. For instance, people use .clear() when they mean ->clear(). + /// @deprecated Use reset() instead because this leads to confusion with clear() methods on the + /// underlying class. For instance, people use .clear() when they mean ->clear(). inline void clear(); -#endif //GLIBMM_DISABLE_DEPRECATED +#endif // GLIBMM_DISABLE_DEPRECATED /** Set underlying instance to 0, decrementing reference count of existing instance appropriately. * @newin{2,16} @@ -146,7 +143,7 @@ class RefPtr * ptr_derived = RefPtr::cast_dynamic(ptr_base); * @endcode */ - template + template static inline RefPtr cast_dynamic(const RefPtr& src); /** Static cast to derived class. @@ -156,7 +153,7 @@ class RefPtr * ptr_derived = RefPtr::cast_static(ptr_base); * @endcode */ - template + template static inline RefPtr cast_static(const RefPtr& src); /** Cast to non-const. @@ -166,7 +163,7 @@ class RefPtr * ptr_unconst = RefPtr::cast_const(ptr_const); * @endcode */ - template + template static inline RefPtr cast_const(const RefPtr& src); /** Compare based on the underlying instance address. @@ -193,73 +190,69 @@ class RefPtr T_CppObject* pCppObject_; }; - #ifndef DOXYGEN_SHOULD_SKIP_THIS // RefPtr<>::operator->() comes first here since it's used by other methods. // If it would come after them it wouldn't be inlined. -template inline -T_CppObject* RefPtr::operator->() const +template +inline T_CppObject* +RefPtr::operator->() const { return pCppObject_; } -template inline -RefPtr::RefPtr() -: - pCppObject_ (nullptr) -{} +template +inline RefPtr::RefPtr() : pCppObject_(nullptr) +{ +} -template inline -RefPtr::~RefPtr() +template +inline RefPtr::~RefPtr() { - if(pCppObject_) + if (pCppObject_) pCppObject_->unreference(); // This could cause pCppObject to be deleted. } -template inline -RefPtr::RefPtr(T_CppObject* pCppObject) -: - pCppObject_ (pCppObject) -{} +template +inline RefPtr::RefPtr(T_CppObject* pCppObject) : pCppObject_(pCppObject) +{ +} -template inline -RefPtr::RefPtr(const RefPtr& src) -: - pCppObject_ (src.pCppObject_) +template +inline RefPtr::RefPtr(const RefPtr& src) : pCppObject_(src.pCppObject_) { - if(pCppObject_) + if (pCppObject_) pCppObject_->reference(); } // The templated ctor allows copy construction from any object that's // castable. Thus, it does downcasts: // base_ref = derived_ref -template - template -inline -RefPtr::RefPtr(const RefPtr& src) -: - // A different RefPtr<> will not allow us access to pCppObject_. We need +template +template +inline RefPtr::RefPtr(const RefPtr& src) +: // A different RefPtr<> will not allow us access to pCppObject_. We need // to add a get_underlying() for this, but that would encourage incorrect // use, so we use the less well-known operator->() accessor: - pCppObject_ (src.operator->()) + pCppObject_(src.operator->()) { - if(pCppObject_) + if (pCppObject_) pCppObject_->reference(); } -template inline -void RefPtr::swap(RefPtr& other) +template +inline void +RefPtr::swap(RefPtr& other) { const auto temp = pCppObject_; pCppObject_ = other.pCppObject_; other.pCppObject_ = temp; } -template inline -RefPtr& RefPtr::operator=(const RefPtr& src) +template +inline RefPtr& +RefPtr::operator=(const RefPtr& src) { // In case you haven't seen the swap() technique to implement copy // assignment before, here's what it does: @@ -285,113 +278,121 @@ RefPtr& RefPtr::operator=(const RefPtr& s // even thinking about it to implement copy assignment whereever the // object data is managed indirectly via a pointer, which is very common. - RefPtr temp (src); + RefPtr temp(src); this->swap(temp); return *this; } -template - template -inline -RefPtr& RefPtr::operator=(const RefPtr& src) +template +template +inline RefPtr& +RefPtr::operator=(const RefPtr& src) { - RefPtr temp (src); + RefPtr temp(src); this->swap(temp); return *this; } -template inline -bool RefPtr::operator==(const RefPtr& src) const +template +inline bool +RefPtr::operator==(const RefPtr& src) const { return (pCppObject_ == src.pCppObject_); } -template inline -bool RefPtr::operator!=(const RefPtr& src) const +template +inline bool +RefPtr::operator!=(const RefPtr& src) const { return (pCppObject_ != src.pCppObject_); } -template inline -RefPtr::operator bool() const +template +inline RefPtr::operator bool() const { return (pCppObject_ != nullptr); } #ifndef GLIBMM_DISABLE_DEPRECATED -template inline -void RefPtr::clear() +template +inline void +RefPtr::clear() { reset(); } -#endif //GLIBMM_DISABLE_DEPRECATED +#endif // GLIBMM_DISABLE_DEPRECATED -template inline -void RefPtr::reset() +template +inline void +RefPtr::reset() { RefPtr temp; // swap with an empty RefPtr<> to clear *this this->swap(temp); } -template - template -inline -RefPtr RefPtr::cast_dynamic(const RefPtr& src) +template +template +inline RefPtr +RefPtr::cast_dynamic(const RefPtr& src) { const auto pCppObject = dynamic_cast(src.operator->()); - if(pCppObject) + if (pCppObject) pCppObject->reference(); return RefPtr(pCppObject); } -template - template -inline -RefPtr RefPtr::cast_static(const RefPtr& src) +template +template +inline RefPtr +RefPtr::cast_static(const RefPtr& src) { const auto pCppObject = static_cast(src.operator->()); - if(pCppObject) + if (pCppObject) pCppObject->reference(); return RefPtr(pCppObject); } -template - template -inline -RefPtr RefPtr::cast_const(const RefPtr& src) +template +template +inline RefPtr +RefPtr::cast_const(const RefPtr& src) { const auto pCppObject = const_cast(src.operator->()); - if(pCppObject) + if (pCppObject) pCppObject->reference(); return RefPtr(pCppObject); } -template inline -bool RefPtr::operator<(const RefPtr& src) const +template +inline bool +RefPtr::operator<(const RefPtr& src) const { return (pCppObject_ < src.pCppObject_); } -template inline -bool RefPtr::operator<=(const RefPtr& src) const +template +inline bool +RefPtr::operator<=(const RefPtr& src) const { return (pCppObject_ <= src.pCppObject_); } -template inline -bool RefPtr::operator>(const RefPtr& src) const +template +inline bool +RefPtr::operator>(const RefPtr& src) const { return (pCppObject_ > src.pCppObject_); } -template inline -bool RefPtr::operator>=(const RefPtr& src) const +template +inline bool +RefPtr::operator>=(const RefPtr& src) const { return (pCppObject_ >= src.pCppObject_); } @@ -399,18 +400,17 @@ bool RefPtr::operator>=(const RefPtr& src) const #endif /* DOXYGEN_SHOULD_SKIP_THIS */ /** @relates Glib::RefPtr */ -template inline -void swap(RefPtr& lhs, RefPtr& rhs) +template +inline void +swap(RefPtr& lhs, RefPtr& rhs) { lhs.swap(rhs); } } // namespace Glib - #endif /* _GLIBMM_REFPTR_H */ - namespace { std::ostringstream result_stream; @@ -418,40 +418,39 @@ std::ostringstream result_stream; class Action : public sigc::trackable { public: - Action() : ref_count(1) { } + Action() : ref_count(1) {} void reference() { ++ref_count; } - void unreference() { if (--ref_count <= 0) delete this; } + void unreference() + { + if (--ref_count <= 0) + delete this; + } void emit_sig1(int n) { sig1.emit(n); } - sigc::signal& signal_sig1() { return sig1; } + sigc::signal& signal_sig1() { return sig1; } private: - sigc::signal sig1; + sigc::signal sig1; int ref_count; - }; class Test : public sigc::trackable { public: - Test() - : action(new Action) + Test() : action(new Action) { result_stream << "new Test; "; -#ifdef ACTIVATE_BUG //See https://bugzilla.gnome.org/show_bug.cgi?id=564005#c14 - action->signal_sig1().connect(sigc::bind(sigc::mem_fun(this, &Test::on_sig1), action)); +#ifdef ACTIVATE_BUG // See https://bugzilla.gnome.org/show_bug.cgi?id=564005#c14 + action->signal_sig1().connect(sigc::bind(sigc::mem_fun(*this, &Test::on_sig1), action)); #else Glib::RefPtr action2(new Action); - action->signal_sig1().connect(sigc::bind(sigc::mem_fun(this, &Test::on_sig1), action2)); + action->signal_sig1().connect(sigc::bind(sigc::mem_fun(*this, &Test::on_sig1), action2)); #endif } - ~Test() - { - result_stream << "delete Test; "; - } + ~Test() { result_stream << "delete Test; "; } void on_sig1(int n, Glib::RefPtr /* action */) { @@ -464,7 +463,8 @@ class Test : public sigc::trackable } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); diff --git a/tests/test_bind_return.cc b/tests/test_bind_return.cc index 88c85ae5..a6dead3c 100644 --- a/tests/test_bind_return.cc +++ b/tests/test_bind_return.cc @@ -1,14 +1,10 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include -#include namespace { @@ -16,28 +12,26 @@ std::ostringstream result_stream; struct foo { - void operator()(int i) - { - result_stream << "foo(int " << i << ") "; - } + void operator()(int i) { result_stream << "foo(int " << i << ") "; } float operator()(float i) { result_stream << "foo(float " << i << ") "; - return i*5; + return i * 5; } }; struct bar : public sigc::trackable { - bar(int i = 0) : i_(i) {} + explicit bar(int i = 0) : i_(i) {} operator int() { return i_; } int i_; }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -52,8 +46,8 @@ int main(int argc, char* argv[]) // references. std::string str("guest book"); // A convoluted way to do - // sigc::bind_return(foo(), sigc::ref(str))(6) = "main"; - sigc::bind_return >(foo(), sigc::ref(str))(6) = "main"; + // sigc::bind_return(foo(), std::ref(str))(6) = "main"; + sigc::bind_return>(foo(), std::ref(str))(6) = "main"; result_stream << str; util->check_result(result_stream, "foo(int 6) main"); @@ -64,10 +58,10 @@ int main(int argc, char* argv[]) // long as there exists a default constructor for it. // // Therefore, we use 'bar', and not 'bar&' for this slot signature. - sigc::slot sl; + sigc::slot sl; { bar choco(-1); - sl = sigc::bind_return(foo(),sigc::ref(choco)); + sl = sigc::bind_return(foo(), std::ref(choco)); result_stream << sl(7); util->check_result(result_stream, "foo(int 7) -1"); } // auto-disconnect diff --git a/tests/test_compose.cc b/tests/test_compose.cc index a626ba62..11b6e3c8 100644 --- a/tests/test_compose.cc +++ b/tests/test_compose.cc @@ -1,15 +1,9 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include - -// assume existance of T_functor::result_type for unknown functor types: -namespace sigc { SIGC_FUNCTORS_HAVE_RESULT_TYPE } namespace { @@ -17,79 +11,49 @@ std::ostringstream result_stream; struct set { - // choose a type that can hold all return values - typedef double result_type; - double operator()(int i) { result_stream << "set(int " << i << ") "; - return i*i; + return i * i; } double operator()(double i) { result_stream << "set(double " << i << ") "; - return i*5; + return i * 5; } }; struct set_void { - typedef void result_type; - - void operator()(double i) - { - result_stream << "set_void(double " << i << ")"; - } + void operator()(double i) { result_stream << "set_void(double " << i << ")"; } }; struct get { -#ifdef SIGC_CXX_TYPEOF - bool operator()() - { - result_stream << "get() "; - return true; - } - - int operator()(int i) - { - result_stream << "get(" << i << ") "; - return i*2; - } - - double operator()(int i, int j) - { - result_stream << "get(" << i << ", " << j << ") "; - return double(i)/double(j); - } -#else - // choose a type that can hold all return values - typedef double result_type; - double operator()() { result_stream << "get() "; - return true; + return static_cast(true); } double operator()(int i) { result_stream << "get(" << i << ") "; - return i*2; + return i * 2; } double operator()(int i, int j) { result_stream << "get(" << i << ", " << j << ") "; - return double(i)/double(j); + return double(i) / double(j); } -#endif }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -105,7 +69,7 @@ int main(int argc, char* argv[]) result_stream << sigc::compose(set(), get())(1, 2); util->check_result(result_stream, "get(1, 2) set(double 0.5) 2.5"); - sigc::compose(set_void(), get())(3); //void test + sigc::compose(set_void(), get())(3); // void test util->check_result(result_stream, "get(3) set_void(double 6)"); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/test_connection.cc b/tests/test_connection.cc new file mode 100644 index 00000000..ec12765b --- /dev/null +++ b/tests/test_connection.cc @@ -0,0 +1,45 @@ +/* Copyright 2019, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include "testutilities.h" +#include +#include +#include + +namespace +{ + +TestUtilities* util = nullptr; +std::ostringstream result_stream; + +void +test_connection_copy_empty() +{ + sigc::connection con1; + + // Try to prevent the compiler from optimising away the copy. + std::cout << &con1 << std::endl; + + sigc::connection con2(con1); + + // Try to prevent the compiler from optimising away the copy. + std::cout << &con2 << std::endl; +} + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_connection_copy_empty(); + + // See also test_disconnection.cc + + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/test_copy_invalid_slot.cc b/tests/test_copy_invalid_slot.cc index b480a154..6b85f604 100644 --- a/tests/test_copy_invalid_slot.cc +++ b/tests/test_copy_invalid_slot.cc @@ -1,22 +1,25 @@ +/* Copyright 2005 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + #include "testutilities.h" -#include -#include #include -#include -#include +#include namespace { std::ostringstream result_stream; -void Foo(sigc::trackable&) +void +Foo(sigc::trackable&) { result_stream << "Foo(x)"; } } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -30,7 +33,7 @@ int main(int argc, char* argv[]) util->check_result(result_stream, "sigc::trackable instance at " + pointer_stream.str()); pointer_stream.str(""); - sigc::slot foo = sigc::bind(sigc::ptr_fun(Foo), sigc::ref(*t)); + sigc::slot foo = sigc::bind(sigc::ptr_fun(Foo), std::ref(*t)); foo(); util->check_result(result_stream, "Foo(x)"); @@ -55,7 +58,7 @@ int main(int argc, char* argv[]) // Now copy foo: up to libsigc++ version 2.0.11, the copy constructor fails // because the pointer value it dereferences does not point to a // sigc::trackable anymore, it now points to a polluted buffer. - sigc::slot bar = foo; + sigc::slot bar = foo; bar(); util->check_result(result_stream, ""); diff --git a/tests/test_cpp11_lambda.cc b/tests/test_cpp11_lambda.cc index e97b80e8..40534e25 100644 --- a/tests/test_cpp11_lambda.cc +++ b/tests/test_cpp11_lambda.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 The libsigc++ Development Team +/* Copyright (C) 2012 - 2016, The libsigc++ Development Team * * This file is part of libsigc++. * @@ -32,7 +32,7 @@ // The only real disadvantage of the C++11 lambda expressions is that a slot that // contains an object derived from sigc::trackable is not automatically disconnected // when the object is deleted, if a reference to the object is stored in a C++11 -// lambda expression, connected to the slot. But if you use sigc::track_obj(), +// lambda expression, connected to the slot. But if you use sigc::track_object(), // the slot is automatically disconnected. Thus, the disadvantage is insignificant. // // To test the C++11 lambda expressions with gcc 4.6.3 (and probably some later @@ -42,31 +42,27 @@ // echo $? // If test_cpp11_lambda writes nothing and the return code is 0, the test has passed. - #include "testutilities.h" -#include #include -#include #include -#include #include #include -#include #include #include - namespace { std::ostringstream result_stream; -int foo(int i, int j) +int +foo(int i, int j) { result_stream << "foo(int " << i << ", int " << j << ") "; - return 4*i + j; + return 4 * i + j; } -void foo_void(int i) +void +foo_void(int i) { result_stream << "foo_void(int " << i << ")"; } @@ -76,16 +72,14 @@ struct bar int test(int i, int j) { result_stream << "bar::test(int " << i << ", int " << j << ") "; - return 4*i + j; + return 4 * i + j; } - void test_void(int i) - { - result_stream << "bar::test_void(int " << i << ")"; - } + void test_void(int i) { result_stream << "bar::test_void(int " << i << ")"; } }; -void egon(std::string& str) +void +egon(std::string& str) { result_stream << "egon(string '" << str << "')"; str = "egon was here"; @@ -94,33 +88,38 @@ void egon(std::string& str) struct book : public sigc::trackable { explicit book(const std::string& name) : name_(name) {} - operator std::string& () { return name_; } + operator std::string&() { return name_; } std::string name_; }; -inline std::ostringstream& operator << (std::ostringstream& s, const book& b) +inline std::ostringstream& +operator<<(std::ostringstream& s, const book& b) { s << b.name_; return s; } -void foo_group1(int i, int j) +void +foo_group1(int i, int j) { result_stream << "foo_group1(int " << i << ", int " << j << ")"; } -int bar_group1(int i) +int +bar_group1(int i) { result_stream << "bar_group1(int " << i << ") "; return i + 2; } -void foo_group2(int i) +void +foo_group2(int i) { result_stream << "foo_group2(int " << i << ")"; } -void foo_group3(int& i) +void +foo_group3(int& i) { result_stream << "foo_group3(int " << i << ")"; ++i; @@ -130,148 +129,156 @@ struct bar_group4 : public sigc::trackable { }; -void foo_group4(bar_group4&) +void +foo_group4(bar_group4&) { result_stream << "foo_group4(bar_group4&)"; } } // end anonymous namespace - - -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - // test lambda operators - //std::cout << "(_1 + _2) (3,4): " << (_1 + _2) (3,4) << std::endl; - result_stream << ([] (int a, int b) -> int { return a + b; }(3,4)); + // std::cout << "(_1 + _2) (3,4): " << (_1 + _2) (3,4) << std::endl; + result_stream << ([](int a, int b) -> int { return a + b; }(3, 4)); util->check_result(result_stream, "7"); - //std::cout << "(_1 + 1) (3,4): " << (_1 + 1) (3,4) << std::endl; - result_stream << ([] (int a, int) -> int { return a + 1; }(3,4)); + // std::cout << "(_1 + 1) (3,4): " << (_1 + 1) (3,4) << std::endl; + result_stream << ([](int a, int) -> int { return a + 1; }(3, 4)); util->check_result(result_stream, "4"); - //std::cout << "(_2 + 1) (3,4): " << (_2 + 1) (3,4) << std::endl; - result_stream << ([] (int, int b) -> int { return b + 1; }(3,4)); + // std::cout << "(_2 + 1) (3,4): " << (_2 + 1) (3,4) << std::endl; + result_stream << ([](int, int b) -> int { return b + 1; }(3, 4)); util->check_result(result_stream, "5"); - //std::cout << "(2 + _1) (3,4): " << (2 + _1) (3,4) << std::endl; - result_stream << ([] (int a, int) -> int { return 2 + a; }(3,4)); + // std::cout << "(2 + _1) (3,4): " << (2 + _1) (3,4) << std::endl; + result_stream << ([](int a, int) -> int { return 2 + a; }(3, 4)); util->check_result(result_stream, "5"); - //std::cout << "(2 + _2) (3,4): " << (2 + _2) (3,4) << std::endl; - result_stream << ([] (int, int b) -> int { return 2 + b; }(3,4)); + // std::cout << "(2 + _2) (3,4): " << (2 + _2) (3,4) << std::endl; + result_stream << ([](int, int b) -> int { return 2 + b; }(3, 4)); util->check_result(result_stream, "6"); - //std::cout << "(_1+_2*_3)(1,2,3): " << (_1+_2*_3)(1,2,3) << std::endl; - result_stream << ([] (int a, int b, int c) -> int { return a + b*c; }(1,2,3)); + // std::cout << "(_1+_2*_3)(1,2,3): " << (_1+_2*_3)(1,2,3) << std::endl; + result_stream << ([](int a, int b, int c) -> int { return a + b * c; }(1, 2, 3)); util->check_result(result_stream, "7"); - //std::cout << "((++_1)*2)(1): " << ((++_1)*2)(1) << std::endl; - result_stream << ([] (int a) -> int { return ++a * 2; }(1)); + // std::cout << "((++_1)*2)(1): " << ((++_1)*2)(1) << std::endl; + result_stream << ([](int a) -> int { return ++a * 2; }(1)); util->check_result(result_stream, "4"); - //std::cout << "((++_1)*2)(a): " << ((++_1)*2)(a); - //std::cout << "; a: " << a << std::endl; + // std::cout << "((++_1)*2)(a): " << ((++_1)*2)(a); + // std::cout << "; a: " << a << std::endl; int a_outer = 1; - result_stream << ([] (int x) -> int { return ++x * 2; }(a_outer)) << " " << a_outer; + result_stream << ([](int x) -> int { return ++x * 2; }(a_outer)) << " " << a_outer; util->check_result(result_stream, "4 1"); - // gcc can't compile libsigc++ lambda expressions with sigc::ref() parameters. + // gcc can't compile libsigc++ lambda expressions with std::ref() parameters. // See https://bugzilla.gnome.org/show_bug.cgi?id=669128 - // std::cout << "((++_1)*2)(ref(a)): " << ((++_1)*2)(sigc::ref(a)); + // std::cout << "((++_1)*2)(ref(a)): " << ((++_1)*2)(std::ref(a)); // std::cout << "; a: " << a << std::endl; - result_stream << ([] (std::reference_wrapper x) -> int { return ++x * 2; }(std::ref(a_outer))); + result_stream << ([](std::reference_wrapper x) -> int + { return ++x * 2; }(std::ref(a_outer))); result_stream << " " << a_outer; util->check_result(result_stream, "4 2"); - result_stream << ([] (int& x) -> int { return ++x * 2; }(a_outer)); + result_stream << ([](int& x) -> int { return ++x * 2; }(a_outer)); result_stream << " " << a_outer; util->check_result(result_stream, "6 3"); - //std::cout << "((++(*_1))*2)(&a): " << ((++(*_1))*2)(&a); - //std::cout << "; a: " << a << std::endl; - result_stream << ([] (int* x) -> int { return ++(*x) * 2; }(&a_outer)); + // std::cout << "((++(*_1))*2)(&a): " << ((++(*_1))*2)(&a); + // std::cout << "; a: " << a << std::endl; + result_stream << ([](int* x) -> int { return ++(*x) * 2; }(&a_outer)); result_stream << " " << a_outer; util->check_result(result_stream, "8 4"); - // std::cout << "((--(*(&_1)))*2)(ref(a)): " << ((--(*(&_1)))*2)(sigc::ref(a)); + // std::cout << "((--(*(&_1)))*2)(ref(a)): " << ((--(*(&_1)))*2)(std::ref(a)); // std::cout << "; a: " << a << std::endl; - result_stream << ([] (std::reference_wrapper x) -> int { return --(*(&x)) * 2; }(std::ref(a_outer))); + result_stream << ([](std::reference_wrapper x) -> int + { return --(*(&x)) * 2; }(std::ref(a_outer))); result_stream << " " << a_outer; util->check_result(result_stream, "6 3"); - result_stream << ([] (int& x) -> int { return --(*(&x)) * 2; }(a_outer)); + result_stream << ([](int& x) -> int { return --(*(&x)) * 2; }(a_outer)); result_stream << " " << a_outer; util->check_result(result_stream, "4 2"); - //std::cout << "(-_1) (-5): " << (-_1) (-5) << std::endl; - result_stream << ([] (int x) -> int { return -x; }(-5)); + // std::cout << "(-_1) (-5): " << (-_1) (-5) << std::endl; + result_stream << ([](int x) -> int { return -x; }(-5)); util->check_result(result_stream, "5"); - //std::cout << "(var(&a)[0])(): " << (sigc::var(&a)[0])() << std::endl; + // std::cout << "(var(&a)[0])(): " << (sigc::var(&a)[0])() << std::endl; result_stream << ([&a_outer]() -> int { return a_outer; }()); util->check_result(result_stream, "2"); - //std::cout << "(_1[_2]) (&a,0): " << (_1[_2]) (&a,0) << std::endl; - result_stream << ([] (int* x, int y) -> int { return x[y]; }(&a_outer,0)); + // std::cout << "(_1[_2]) (&a,0): " << (_1[_2]) (&a,0) << std::endl; + result_stream << ([](int* x, int y) -> int { return x[y]; }(&a_outer, 0)); util->check_result(result_stream, "2"); - //std::cout << "(*_1=_2) (&a,1): " << (*_1=_2) (&a,1) << std::endl; - result_stream << ([] (int* x, int y) -> int { *x = y; return *x; }(&a_outer,1)); + // std::cout << "(*_1=_2) (&a,1): " << (*_1=_2) (&a,1) << std::endl; + result_stream << ([](int* x, int y) -> int { + *x = y; + return *x; + }(&a_outer, 1)); util->check_result(result_stream, "1"); // Comma operator, https://bugzilla.gnome.org/show_bug.cgi?id=342911 a_outer = -1; int b_outer = -1; int c_outer = -1; - //std::cout << "(var(c) = (var(a) = _1, var(b) = _2))(2,3): " + // std::cout << "(var(c) = (var(a) = _1, var(b) = _2))(2,3): " // << (sigc::var(c) = (sigc::var(a) = _1, sigc::var(b) = _2))(2,3); - //std::cout << "; a: " << a << "; b: " << b << "; c: " << c << std::endl; - result_stream << ([&a_outer,&b_outer,&c_outer](int x, int y) -> int { return c_outer = (a_outer = x, b_outer = y); }(2,3)); + // std::cout << "; a: " << a << "; b: " << b << "; c: " << c << std::endl; + result_stream << ([&a_outer, &b_outer, &c_outer](int x, int y) -> int + { return c_outer = (a_outer = x, b_outer = y); }(2, 3)); result_stream << " " << a_outer << " " << b_outer << " " << c_outer; util->check_result(result_stream, "3 2 3 3"); // c++ restrictions: // - ref() must be used to indicate that the value shall not be copied // - constant() is used to create a lambda and delay execution of "std::cout << 1" - // - var() is used to create a lambda that holds a reference and is interchangable with ref() in lambda operator expressions + // - var() is used to create a lambda that holds a reference and is interchangable with ref() in + // lambda operator expressions // - cannot use std::endl without much hackery because it is defined as a template function // - cannot use "\n" without var() because arrays cannot be copied - // (sigc::ref(std::cout) << sigc::constant(1) << sigc::var("\n"))(); - [](){ result_stream << 1 << "\n"; }(); + // (std::ref(std::cout) << sigc::constant(1) << sigc::var("\n"))(); + []() { result_stream << 1 << "\n"; }(); util->check_result(result_stream, "1\n"); - //(sigc::ref(std::cout) << _1 << std::string("\n"))("hello world"); - [](const char* a){ result_stream << a << std::string("\n"); }("hello world"); + //(std::ref(std::cout) << _1 << std::string("\n"))("hello world"); + [](const char* a) { result_stream << a << std::string("\n"); }("hello world"); util->check_result(result_stream, "hello world\n"); - //(sigc::ref(std::cout) << sigc::static_cast_(_1) << std::string("\n"))(1.234); - [](double a){ result_stream << static_cast(a) << std::string("\n"); }(1.234); + //(std::ref(std::cout) << sigc::static_cast_(_1) << std::string("\n"))(1.234); + [](double a) { result_stream << static_cast(a) << std::string("\n"); }(1.234); util->check_result(result_stream, "1\n"); // (sigc::var(std::cout) << 1 << sigc::var("\n"))(); - [](){ result_stream << 1 << "\n"; }(); + []() { result_stream << 1 << "\n"; }(); util->check_result(result_stream, "1\n"); //(sigc::var(std::cout) << _1 << std::string("\n"))("hello world"); - [](const char* a){ result_stream << a << std::string("\n"); }("hello world"); + [](const char* a) { result_stream << a << std::string("\n"); }("hello world"); util->check_result(result_stream, "hello world\n"); // auto-disconnect // Here's an area where the libsigc++ lambda expressions are advantageous. // If you want to auto-disconnect a slot with a C++11 lambda expression // that contains references to sigc::trackable-derived objects, you must use - // sigc::track_obj(). - sigc::slot sl1; + // sigc::track_object(). + sigc::slot sl1; { book guest_book("karl"); - //sl1 = (sigc::var(std::cout) << sigc::ref(guest_book) << sigc::var("\n")); - // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; // no auto-disconnect - sl1 = sigc::track_obj([&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }, guest_book); + // sl1 = (sigc::var(std::cout) << std::ref(guest_book) << sigc::var("\n")); + // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; // no + // auto-disconnect + sl1 = sigc::track_object( + [&guest_book](std::ostringstream& stream) { stream << guest_book << "\n"; }, guest_book); sl1(result_stream); util->check_result(result_stream, "karl\n"); @@ -282,27 +289,29 @@ int main(int argc, char* argv[]) // test group adaptor, here replaced by std::bind bar the_bar; - //std::cout << (sigc::group(&foo, _1, _2)) (1, 2) << std::endl; + // std::cout << (sigc::group(&foo, _1, _2)) (1, 2) << std::endl; result_stream << std::bind(&foo, std::placeholders::_1, std::placeholders::_2)(1, 2); util->check_result(result_stream, "foo(int 1, int 2) 6"); - //std::cout << (sigc::group(&foo, _2, _1)) (1, 2) << std::endl; + // std::cout << (sigc::group(&foo, _2, _1)) (1, 2) << std::endl; result_stream << std::bind(&foo, std::placeholders::_2, std::placeholders::_1)(1, 2); util->check_result(result_stream, "foo(int 2, int 1) 9"); - //std::cout << (sigc::group(sigc::mem_fun(&bar::test), _1, _2, _3)) (sigc::ref(the_bar), 1, 2) << std::endl; + // std::cout << (sigc::group(sigc::mem_fun(&bar::test), _1, _2, _3)) (std::ref(the_bar), 1, 2) << + // std::endl; // std::ref(the_bar) is not necessary. It can make the call ambiguous. // Even without std::ref() the_bar is not copied. - result_stream << std::bind(std::mem_fn(&bar::test), std::placeholders::_1, - std::placeholders::_2, std::placeholders::_3)(the_bar, 1, 2); + result_stream << std::bind( + std::mem_fn(&bar::test), std::placeholders::_1, std::placeholders::_2, std::placeholders::_3)( + the_bar, 1, 2); util->check_result(result_stream, "bar::test(int 1, int 2) 6"); // same functionality as bind - //std::cout << (sigc::group(&foo, _1, 2)) (1) << std::endl; + // std::cout << (sigc::group(&foo, _1, 2)) (1) << std::endl; result_stream << std::bind(&foo, std::placeholders::_1, 2)(1); util->check_result(result_stream, "foo(int 1, int 2) 6"); - //std::cout << (sigc::group(&foo, 1, 2)) () << std::endl; + // std::cout << (sigc::group(&foo, 1, 2)) () << std::endl; result_stream << std::bind(&foo, 1, 2)(); util->check_result(result_stream, "foo(int 1, int 2) 6"); @@ -317,17 +326,17 @@ int main(int argc, char* argv[]) // functor has an unambiguous operator()(). // auto-disconnect - sigc::slot sl2; + sigc::slot sl2; { book guest_book("karl"); - //sl2 = sigc::group(&egon, sigc::ref(guest_book)); + // sl2 = sigc::group(&egon, std::ref(guest_book)); // sl2 = [&guest_book] () { egon(guest_book); }; // no auto-disconnect // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) - sl2 = sigc::track_obj([&guest_book] () { egon(guest_book); }, guest_book); + sl2 = sigc::track_object([&guest_book]() { egon(guest_book); }, guest_book); sl2(); util->check_result(result_stream, "egon(string 'karl')"); - //std::cout << static_cast(guest_book) << std::endl; + // std::cout << static_cast(guest_book) << std::endl; result_stream << static_cast(guest_book); util->check_result(result_stream, "egon was here"); @@ -339,15 +348,15 @@ int main(int argc, char* argv[]) // More auto-disconnect { book guest_book("charlie"); - //sl2 = sigc::group(&egon, sigc::ref(guest_book)); + // sl2 = sigc::group(&egon, std::ref(guest_book)); // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) auto fn2 = std::bind(&egon, std::ref(guest_book)); - //sl2 = fn2; // no auto-disconnect - sl2 = sigc::track_obj(fn2, guest_book); + // sl2 = fn2; // no auto-disconnect + sl2 = sigc::track_object(fn2, guest_book); sl2(); util->check_result(result_stream, "egon(string 'charlie')"); - //std::cout << static_cast(guest_book) << std::endl; + // std::cout << static_cast(guest_book) << std::endl; result_stream << static_cast(guest_book); util->check_result(result_stream, "egon was here"); @@ -357,8 +366,8 @@ int main(int argc, char* argv[]) util->check_result(result_stream, ""); // same functionality as hide - //std::cout << (sigc::group(&foo, _1, _2)) (1,2,3) << std::endl; - result_stream << std::bind(&foo, std::placeholders::_1, std::placeholders::_2)(1,2,3); + // std::cout << (sigc::group(&foo, _1, _2)) (1,2,3) << std::endl; + result_stream << std::bind(&foo, std::placeholders::_1, std::placeholders::_2)(1, 2, 3); util->check_result(result_stream, "foo(int 1, int 2) 6"); //(sigc::group(sigc::ptr_fun(&foo_void), _2)) (1, 2); @@ -366,14 +375,15 @@ int main(int argc, char* argv[]) util->check_result(result_stream, "foo_void(int 2)"); // same functionality as compose - //std::cout << (sigc::group(&foo, sigc::group(&foo, _1, _2), _3)) (1,2,3) << std::endl; - result_stream << std::bind(&foo, std::bind(&foo, std::placeholders::_1, std::placeholders::_2), - std::placeholders::_3)(1,2,3); + // std::cout << (sigc::group(&foo, sigc::group(&foo, _1, _2), _3)) (1,2,3) << std::endl; + result_stream << std::bind(&foo, + std::bind(&foo, std::placeholders::_1, std::placeholders::_2), + std::placeholders::_3)(1, 2, 3); util->check_result(result_stream, "foo(int 1, int 2) foo(int 6, int 3) 27"); // same functionality as retype - //std::cout << (sigc::group(&foo, sigc::static_cast_(_1), 2)) (1.234) << std::endl; - result_stream << ([] (double x) -> int { return foo(static_cast(x), 2); }(1.234)); + // std::cout << (sigc::group(&foo, sigc::static_cast_(_1), 2)) (1.234) << std::endl; + result_stream << ([](double x) -> int { return foo(static_cast(x), 2); }(1.234)); util->check_result(result_stream, "foo(int 1, int 2) 6"); // Code examples with C++11 lambda expressions and std::bind, which can replace @@ -382,26 +392,26 @@ int main(int argc, char* argv[]) //--- sigc++/adaptors/lambda/macros/base.h.m4 - //std::cout << sigc::_1(10,20,30); // returns 10 - result_stream << ([] (int x, int, int) -> int { return x; }(10,20,30)); + // std::cout << sigc::_1(10,20,30); // returns 10 + result_stream << ([](int x, int, int) -> int { return x; }(10, 20, 30)); util->check_result(result_stream, "10"); - //std::cout << sigc::_2(10,20,30); // returns 20 - result_stream << ([] (int, int y, int) -> int { return y; }(10,20,30)); + // std::cout << sigc::_2(10,20,30); // returns 20 + result_stream << ([](int, int y, int) -> int { return y; }(10, 20, 30)); util->check_result(result_stream, "20"); - //std::cout << (sigc::_1 + 5)(3); // returns (3 + 5) - result_stream << ([] (int x) -> int { return x + 5; }(3)); + // std::cout << (sigc::_1 + 5)(3); // returns (3 + 5) + result_stream << ([](int x) -> int { return x + 5; }(3)); util->check_result(result_stream, "8"); - //std::cout << (sigc::_1 * sigc::_2)(7,10); // returns (7 * 10) - result_stream << ([] (int x, int y) -> int { return x * y; }(7,10)); + // std::cout << (sigc::_1 * sigc::_2)(7,10); // returns (7 * 10) + result_stream << ([](int x, int y) -> int { return x * y; }(7, 10)); util->check_result(result_stream, "70"); - //int main(int argc, char* argv[]) + // int main(int argc, char* argv[]) //{ // int data; - // sigc::signal readValue; + // sigc::signal readValue; // // readValue.connect(sigc::var(data)); // @@ -413,9 +423,9 @@ int main(int argc, char* argv[]) //} { int data; - sigc::signal readValue; + sigc::signal readValue; - readValue.connect([&data] () -> int { return data; }); + readValue.connect([&data]() -> int { return data; }); data = 3; result_stream << readValue(); @@ -429,65 +439,70 @@ int main(int argc, char* argv[]) //--- sigc++/adaptors/lambda/macros/group.h.m4 // argument binding ... - //sigc::group(&foo,10,sigc::_1)(20); //fixes the first argument and calls foo(10,20) + // sigc::group(&foo,10,sigc::_1)(20); //fixes the first argument and calls foo(10,20) std::bind(&foo_group1, 10, std::placeholders::_1)(20); util->check_result(result_stream, "foo_group1(int 10, int 20)"); - //sigc::group(&foo,sigc::_1,30)(40); //fixes the second argument and calls foo(40,30) + // sigc::group(&foo,sigc::_1,30)(40); //fixes the second argument and calls foo(40,30) std::bind(&foo_group1, std::placeholders::_1, 30)(40); util->check_result(result_stream, "foo_group1(int 40, int 30)"); // argument reordering ... - //sigc::group(&foo,sigc::_2,sigc::_1)(1,2); //calls foo(2,1) - std::bind(&foo_group1, std::placeholders::_2, std::placeholders::_1)(1,2); + // sigc::group(&foo,sigc::_2,sigc::_1)(1,2); //calls foo(2,1) + std::bind(&foo_group1, std::placeholders::_2, std::placeholders::_1)(1, 2); util->check_result(result_stream, "foo_group1(int 2, int 1)"); // argument hiding ... - //sigc::group(&foo,sigc::_1,sigc::_2)(1,2,3); //calls foo(1,2) - std::bind(&foo_group1, std::placeholders::_1, std::placeholders::_2)(1,2,3); + // sigc::group(&foo,sigc::_1,sigc::_2)(1,2,3); //calls foo(1,2) + std::bind(&foo_group1, std::placeholders::_1, std::placeholders::_2)(1, 2, 3); util->check_result(result_stream, "foo_group1(int 1, int 2)"); // functor composition ... - //sigc::group(&foo,sigc::_1,sigc::group(&bar,sigc::_2))(1,2); //calls foo(1,bar(2)) - std::bind(&foo_group1, std::placeholders::_1, std::bind(&bar_group1, std::placeholders::_2))(1,2); + // sigc::group(&foo,sigc::_1,sigc::group(&bar,sigc::_2))(1,2); //calls foo(1,bar(2)) + std::bind(&foo_group1, std::placeholders::_1, std::bind(&bar_group1, std::placeholders::_2))( + 1, 2); util->check_result(result_stream, "bar_group1(int 2) foo_group1(int 1, int 4)"); // algebraic expressions ... // sigc::group(&foo,sigc::_1*sigc::_2,sigc::_1/sigc::_2)(6,3); //calls foo(6*3,6/3) - [] (int x, int y) { foo_group1(x*y, x/y); }(6,3); + [](int x, int y) { foo_group1(x * y, x / y); }(6, 3); util->check_result(result_stream, "foo_group1(int 18, int 2)"); { - sigc::signal some_signal; - //some_signal.connect(sigc::group(&foo,sigc::_2)); - //some_signal.connect(std::bind(&foo_group2, std::placeholders::_2)); // does not compile (gcc 4.6.3) + sigc::signal some_signal; + // some_signal.connect(sigc::group(&foo,sigc::_2)); + // some_signal.connect(std::bind(&foo_group2, std::placeholders::_2)); // does not compile (gcc + // 4.6.3) some_signal.connect([](int, int y) { foo_group2(y); }); - some_signal.emit(1,2); + some_signal.emit(1, 2); util->check_result(result_stream, "foo_group2(int 2)"); } { int some_int = 0; - sigc::signal some_signal; - //some_signal.connect(sigc::group(&foo,sigc::ref(some_int))); - //some_signal.connect(std::bind(&foo_group3, std::ref(some_int))); // does not compile (gcc 4.6.3) - //some_signal.connect(sigc::bind(&foo_group3, sigc::ref(some_int))); // compiles, but we prefer std::bind() or C++11 lambda - some_signal.connect([&some_int](){ foo_group3(some_int); }); + sigc::signal some_signal; + // some_signal.connect(sigc::group(&foo,std::ref(some_int))); + // some_signal.connect(std::bind(&foo_group3, std::ref(some_int))); // does not compile (gcc + // 4.6.3) + // some_signal.connect(sigc::bind(&foo_group3, std::ref(some_int))); // compiles, but we prefer + // std::bind() or C++11 lambda + some_signal.connect([&some_int]() { foo_group3(some_int); }); some_signal.emit(); result_stream << " " << some_int; util->check_result(result_stream, "foo_group3(int 0) 1"); } { - //struct bar : public sigc::trackable {} some_bar; - sigc::signal some_signal; + // struct bar : public sigc::trackable {} some_bar; + sigc::signal some_signal; { bar_group4 some_bar; - //some_signal.connect(sigc::group(&foo,sigc::ref(some_bar))); + // some_signal.connect(sigc::group(&foo, std::ref(some_bar))); // disconnected automatically if some_bar goes out of scope - //some_signal.connect([&some_bar](){ foo_group4(some_bar); }); // no auto-disconnect - //some_signal.connect(sigc::bind(&foo_group4, sigc::ref(some_bar))); // auto-disconnects, but we prefer C++11 lambda - some_signal.connect(sigc::track_obj([&some_bar](){ foo_group4(some_bar); }, some_bar)); + // some_signal.connect([&some_bar](){ foo_group4(some_bar); }); // no auto-disconnect + // some_signal.connect(sigc::bind(&foo_group4, std::ref(some_bar))); // auto-disconnects, but + // we prefer C++11 lambda + some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); some_signal.emit(); util->check_result(result_stream, "foo_group4(bar_group4&)"); } diff --git a/tests/test_custom.cc b/tests/test_custom.cc index 8b4e0f6c..50e4df1b 100644 --- a/tests/test_custom.cc +++ b/tests/test_custom.cc @@ -1,10 +1,12 @@ +/* Copyright 2005 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + // Write your custom tests here so you don't have to think about how to compile // and execute your test code against the exact same library that you are // currently hacking. #include "testutilities.h" -#include -#include #include namespace @@ -13,7 +15,8 @@ std::ostringstream result_stream; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); diff --git a/tests/test_deduce_result_type.cc b/tests/test_deduce_result_type.cc deleted file mode 100644 index 423d8cd2..00000000 --- a/tests/test_deduce_result_type.cc +++ /dev/null @@ -1,76 +0,0 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team - * Assigned to public domain. Use as you wish without restriction. - */ - -#include "testutilities.h" -#include -#include -#include - -namespace -{ -std::ostringstream result_stream; - -template -void bar(T) -{ - result_stream << "unknown"; -} - -template <> -void bar(int) -{ - result_stream << "int"; -} - -template <> -void bar(double) -{ - result_stream << "double"; -} - -struct foo : public sigc::functor_base -{ - typedef double result_type; - - int operator()(int i = 1); - double operator()(const int&, int); -}; - -struct foo2 : public foo -{}; - -struct foo3 : public sigc::functor_base -{ - typedef int result_type; - - int operator()(int i = 1); - double operator()(const int&, int); -}; - -} // end anonymous namespace - -int main(int argc, char* argv[]) -{ - auto util = TestUtilities::get_instance(); - - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - - bar(sigc::deduce_result_t()); - util->check_result(result_stream, "double"); - - bar(sigc::deduce_result_t()); - util->check_result(result_stream, "double"); - - bar(sigc::deduce_result_t()); - util->check_result(result_stream, "int"); - -#ifdef FAIL - bar(sigc::deduce_result_t()); - util->check_result(result_stream, "double"); -#endif - - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/tests/test_disconnect.cc b/tests/test_disconnect.cc index 048acbd0..28ff1e3f 100644 --- a/tests/test_disconnect.cc +++ b/tests/test_disconnect.cc @@ -1,32 +1,28 @@ -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include #include -#include -#include -#include -#include -//The Tru64 compiler seems to need this to avoid an unresolved symbol -//See bug #161503 -#include +// The Tru64 compiler seems to need this to avoid an unresolved symbol +// See bug #161503 namespace { std::ostringstream result_stream; -int foo(int i) +int +foo(int i) { result_stream << "foo(" << i << ") "; return 1; } -int bar(double i) +int +bar(double i) { result_stream << "bar(" << i << ") "; return 1; @@ -41,7 +37,8 @@ struct A : public sigc::trackable } }; -void good_bye_world() +void +good_bye_world() { result_stream << "Good bye world!"; } @@ -50,88 +47,85 @@ struct B : public sigc::trackable { B() { - sig.connect(sigc::mem_fun(this, &B::destroy)); - sig.connect(sigc::mem_fun(this, &B::boom)); + sig.connect(sigc::mem_fun(*this, &B::destroy)); + sig.connect(sigc::mem_fun(*this, &B::boom)); sig.connect(sigc::ptr_fun(&good_bye_world)); } - void destroy() // Calling destroy() during signal emission seems weird! - { // However, if this works, anything will work! - delete this; // valgrind reports a small memory leak, that's all. + void destroy() // Calling destroy() during signal emission seems weird! + { // However, if this works, anything will work! + delete this; // valgrind reports a small memory leak, that's all. } - void boom() - { - result_stream << "boom!"; - } + void boom() { result_stream << "boom!"; } - void emit() - { - sig.emit(); - } + void emit() { sig.emit(); } - sigc::signal sig; + sigc::signal sig; }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::signal sig; - sigc::signal::iterator confoo; - sigc::signal::iterator conbar; - sigc::connection cona; // connection objects are safe to use beyond the life time of a signal. + sigc::signal sig; + sigc::connection confoo; + sigc::connection conbar; + sigc::connection cona; // connection objects are safe to use beyond the life time of a signal. { A a; - sig.connect(sigc::mem_fun1(&a, &A::foo)); - confoo = sig.connect(sigc::ptr_fun1(&foo)); - conbar = sig.connect(sigc::ptr_fun1(&bar)); + sig.connect(sigc::mem_fun(a, &A::foo)); + confoo = sig.connect(sigc::ptr_fun(&foo)); + conbar = sig.connect(sigc::ptr_fun(&bar)); result_stream << "sig is connected to A::foo, foo, bar (size=" << sig.size() << "): "; sig(1); - util->check_result(result_stream, - "sig is connected to A::foo, foo, bar (size=3): A::foo(1) foo(1) bar(1) "); - } // auto disconnection! iterators stay valid after disconnections. + util->check_result( + result_stream, "sig is connected to A::foo, foo, bar (size=3): A::foo(1) foo(1) bar(1) "); + } // auto disconnection! iterators stay valid after disconnections. result_stream << "sig is connected to foo, bar (size=" << sig.size() << "): "; sig(2); util->check_result(result_stream, "sig is connected to foo, bar (size=2): foo(2) bar(2) "); - A a; // iterators stay valid after further connections. - cona = sig.slots().insert(conbar, sigc::mem_fun1(&a, &A::foo)); + A a; // iterators stay valid after further connections. + cona = sig.connect(sigc::mem_fun(a, &A::foo)); result_stream << "sig is connected to foo, A::foo, bar (size=" << sig.size() << "): "; sig(3); - util->check_result(result_stream, - "sig is connected to foo, A::foo, bar (size=3): foo(3) A::foo(3) bar(3) "); + util->check_result( + result_stream, "sig is connected to foo, A::foo, bar (size=3): foo(3) bar(3) A::foo(3) "); - conbar->disconnect(); // manual disconnection + conbar.disconnect(); // manual disconnection result_stream << "sig is connected to foo, A::foo (size=" << sig.size() << "): "; sig(4); util->check_result(result_stream, "sig is connected to foo, A::foo (size=2): foo(4) A::foo(4) "); - confoo->disconnect(); // manual disconnection + confoo.disconnect(); // manual disconnection result_stream << "sig is connected to A::foo (size=" << sig.size() << "): "; sig(5); util->check_result(result_stream, "sig is connected to A::foo (size=1): A::foo(5) "); - cona.disconnect(); // manual disconnection + cona.disconnect(); // manual disconnection result_stream << "sig is empty (size=" << sig.size() << "): "; sig(6); util->check_result(result_stream, "sig is empty (size=0): "); - cona.disconnect(); // already disconnected -> legal with connection objects, however, nothing happens ... + cona.disconnect(); // already disconnected -> legal with connection objects, however, nothing + // happens ... { A a2; - sig.connect(sigc::compose(sigc::mem_fun(&a2, &A::foo), &foo)); + sig.connect(sigc::compose(sigc::mem_fun(a2, &A::foo), &foo)); result_stream << "sig is connected to compose(A::foo, foo) (size=" << sig.size() << "): "; sig(7); - util->check_result(result_stream, "sig is connected to compose(A::foo, foo) (size=1): foo(7) A::foo(1) "); + util->check_result( + result_stream, "sig is connected to compose(A::foo, foo) (size=1): foo(7) A::foo(1) "); } result_stream << "sig is empty (size=" << sig.size() << "): "; sig(8); @@ -139,11 +133,13 @@ int main(int argc, char* argv[]) { // A slot# within a slot A a2; - sigc::slot1 setter = sigc::mem_fun(&a2, &A::foo); + sigc::slot setter = sigc::mem_fun(a2, &A::foo); sig.connect(sigc::compose(setter, &foo)); - result_stream << "sig is connected to compose(slot1(A::foo), foo) (size=" << sig.size() << "): "; + result_stream << "sig is connected to compose(slot1(A::foo), foo) (size=" << sig.size() + << "): "; sig(9); - util->check_result(result_stream, "sig is connected to compose(slot1(A::foo), foo) (size=1): foo(9) A::foo(1) "); + util->check_result( + result_stream, "sig is connected to compose(slot1(A::foo), foo) (size=1): foo(9) A::foo(1) "); } result_stream << "sig is empty (size=" << sig.size() << "): "; sig(10); @@ -151,18 +147,19 @@ int main(int argc, char* argv[]) { // A slot within a slot A a2; - sigc::slot setter = sigc::mem_fun(&a2, &A::foo); + sigc::slot setter = sigc::mem_fun(a2, &A::foo); sig.connect(sigc::compose(setter, &foo)); result_stream << "sig is connected to compose(slot(A::foo), foo) (size=" << sig.size() << "): "; sig(11); - util->check_result(result_stream, "sig is connected to compose(slot(A::foo), foo) (size=1): foo(11) A::foo(1) "); + util->check_result( + result_stream, "sig is connected to compose(slot(A::foo), foo) (size=1): foo(11) A::foo(1) "); } result_stream << "sig is empty (size=" << sig.size() << "): "; sig(12); util->check_result(result_stream, "sig is empty (size=0): "); result_stream << "deleting a signal during emission... "; - auto b = new B; + auto b = new B; // This is deleted by B::destroy(). b->emit(); util->check_result(result_stream, "deleting a signal during emission... Good bye world!"); diff --git a/tests/test_disconnect_during_emit.cc b/tests/test_disconnect_during_emit.cc index 07232426..b746c21f 100644 --- a/tests/test_disconnect_during_emit.cc +++ b/tests/test_disconnect_during_emit.cc @@ -1,4 +1,4 @@ -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ @@ -29,7 +29,8 @@ class HandlerClass : public sigc::trackable } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -38,7 +39,7 @@ int main(int argc, char* argv[]) HandlerClass instance; - sigc::signal signal_test; + sigc::signal signal_test; connection = signal_test.connect(sigc::mem_fun(instance, &HandlerClass::handler)); result_stream << "Number of signal handlers before signal emission: " << signal_test.size(); util->check_result(result_stream, "Number of signal handlers before signal emission: 1"); diff --git a/tests/test_exception_catch.cc b/tests/test_exception_catch.cc index f8f6e02e..29c8b320 100644 --- a/tests/test_exception_catch.cc +++ b/tests/test_exception_catch.cc @@ -1,22 +1,16 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include -#include namespace { std::ostringstream result_stream; -struct f : public sigc::functor_base +struct f { - typedef int result_type; - int operator()(int i) { result_stream << "f(int " << i << ") "; @@ -24,10 +18,8 @@ struct f : public sigc::functor_base } }; -struct g : public sigc::functor_base +struct g { - typedef int result_type; - int operator()() { result_stream << "g() "; @@ -35,10 +27,8 @@ struct g : public sigc::functor_base } }; -struct g_void : public sigc::functor_base +struct g_void { - typedef void result_type; - void operator()() { result_stream << "g_void() "; @@ -54,7 +44,7 @@ struct my_catch { throw; } - catch (std::range_error e) // catch what types we know + catch (const std::range_error& e) // catch what types we know { result_stream << "caught " << e.what(); } @@ -63,9 +53,27 @@ struct my_catch } }; +struct my_catch_void +{ + void operator()() + { + try + { + throw; + } + catch (const std::range_error& e) // catch what types we know + { + result_stream << "caught " << e.what(); + } + + // all else continues out. + } +}; + } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -78,7 +86,7 @@ int main(int argc, char* argv[]) result_stream << sigc::exception_catch(g(), my_catch())(); util->check_result(result_stream, "g() caught out of range 1"); - sigc::exception_catch(g_void(), my_catch())(); // void test + sigc::exception_catch(g_void(), my_catch_void())(); // void test util->check_result(result_stream, "g_void() caught out of range "); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/test_functor_trait.cc b/tests/test_functor_trait.cc deleted file mode 100644 index bf3b26e4..00000000 --- a/tests/test_functor_trait.cc +++ /dev/null @@ -1,98 +0,0 @@ -/* Copyright 2002, The libsigc++ Development Team - * Assigned to public domain. Use as you wish without restriction. - */ - -#include "testutilities.h" -#include -#include -#include -#include -#include -#include - -namespace -{ -std::ostringstream result_stream; - -class trackable {}; - -struct A : public trackable { A() {} }; - -template ::value> -struct with_trackable; - -template -struct with_trackable -{ - static void perform(const T_type&) - { - result_stream << "other "; - } -}; - -template -struct with_trackable -{ - static void perform(const T_type&) - { - result_stream << "trackable "; - } - - static void perform(T_type*) - { - result_stream << "trackable* "; - } - - static void perform(const T_type*) - { - result_stream << "const trackable* "; - } -}; - -struct print -{ - void operator()(int i) const - { - result_stream << "int: " << i << " "; - } - - template - void operator()(const T& t) const - { - with_trackable::perform(t); - } -}; - -void foo(int, int, int) -{} - -void bar(int) -{} - -} // end anonymous namespace - -int main(int argc, char* argv[]) -{ - auto util = TestUtilities::get_instance(); - - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - - int i = 1; - int j = 2; - int k = 3; - A a; - result_stream << "hit all targets: "; - sigc::visit_each(print(), sigc::compose(sigc::bind(sigc::ptr_fun3(&foo), sigc::ref(a), i), sigc::ptr_fun1(&bar))); - util->check_result(result_stream, "hit all targets: other trackable int: 1 other "); - - result_stream << "hit all ints: "; - sigc::visit_each_type(print(), sigc::compose(sigc::bind(sigc::ptr_fun3(&foo), sigc::ref(a), j),sigc::ptr_fun1(&bar))); - util->check_result(result_stream, "hit all ints: int: 2 "); - - result_stream << "hit all trackable: "; - sigc::visit_each_type(print(), sigc::compose(sigc::bind(sigc::ptr_fun3(&foo), sigc::ref(a), k),sigc::ptr_fun1(&bar))); - util->check_result(result_stream, "hit all trackable: trackable "); - - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; -} diff --git a/tests/test_hide.cc b/tests/test_hide.cc index c1cdad2f..bec7def4 100644 --- a/tests/test_hide.cc +++ b/tests/test_hide.cc @@ -1,22 +1,16 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include namespace { std::ostringstream result_stream; -struct foo : public sigc::functor_base +struct foo { - // choose a type that can hold all return values - typedef int result_type; - int operator()() { result_stream << "foo() "; @@ -30,26 +24,20 @@ struct foo : public sigc::functor_base } }; -struct foo_void : public sigc::functor_base +struct foo_void { - typedef void result_type; - - void operator()() - { - result_stream << "foo_void()"; - } + void operator()() { result_stream << "foo_void()"; } }; } // end anonymous namespace -namespace sigc { SIGC_FUNCTOR_TRAIT(foo,bool) } - -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + return TestUtilities::get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; result_stream << sigc::hide<0>(foo())(1, 2); util->check_result(result_stream, "foo(int 2) 3"); @@ -66,5 +54,5 @@ int main(int argc, char* argv[]) sigc::hide(foo_void())(1); // void test util->check_result(result_stream, "foo_void()"); - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + return TestUtilities::get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_limit_reference.cc b/tests/test_limit_reference.cc index d72efd18..a115d6dc 100644 --- a/tests/test_limit_reference.cc +++ b/tests/test_limit_reference.cc @@ -1,38 +1,43 @@ +/* Copyright 2005 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + #include "testutilities.h" #include -#include -#include namespace { std::ostringstream result_stream; -class Base - : virtual public sigc::trackable +class Base : virtual public sigc::trackable { +public: + Base() {} + + Base(const Base& src) = default; + Base& operator=(const Base& src) = default; + Base(Base&& src) = delete; + Base& operator=(Base&& src) = delete; }; class Base2 { public: - virtual ~Base2() - {} + virtual ~Base2() {} }; class Derived - : virtual public Base, - public Base2 +: virtual public Base +, public Base2 { public: - void method() - { - result_stream << "method()"; - } + void method() { result_stream << "method()"; } }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -40,17 +45,15 @@ int main(int argc, char* argv[]) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; auto instance = new Derived(); - sigc::slot handler = sigc::mem_fun(instance, &Derived::method); + sigc::slot handler = sigc::mem_fun(*instance, &Derived::method); handler(); util->check_result(result_stream, "method()"); - auto param = - sigc::bind(sigc::slot(), sigc::ref(*instance)); + sigc::slot param = sigc::bind(sigc::slot(), std::ref(*instance)); param(); util->check_result(result_stream, ""); - auto ret = - sigc::bind_return(sigc::slot(), sigc::ref(*instance)); + sigc::slot ret = sigc::bind_return(sigc::slot(), std::ref(*instance)); ret(); util->check_result(result_stream, ""); diff --git a/tests/test_mem_fun.cc b/tests/test_mem_fun.cc index 32e568bf..ee344afb 100644 --- a/tests/test_mem_fun.cc +++ b/tests/test_mem_fun.cc @@ -1,31 +1,21 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include - -//TODO: put something like #ifndef FORTE (some older version, I think) or AIX xlC... #else ... #endif around: -#define ENABLE_TEST_OF_OVERLOADED_FUNCTIONS 0 namespace { + +TestUtilities* util = nullptr; std::ostringstream result_stream; struct test { - void foo(short i1) - { - result_stream << "test::foo(short " << i1 << ')'; - } + void foo(short i1) { result_stream << "test::foo(short " << i1 << ')'; } - void foo_const(int i1) const - { - result_stream << "test::foo_const(int " << i1 << ')'; - } + void foo_const(int i1) const { result_stream << "test::foo_const(int " << i1 << ')'; } void foo_volatile(float i1) volatile { @@ -37,17 +27,12 @@ struct test result_stream << "test::foo_const_volatile(double " << i1 << ')'; } - void foo_overloaded(char i1) - { - result_stream << "test::foo_overloaded(char " << int(i1) << ')'; - } + void foo_overloaded(char i1) { result_stream << "test::foo_overloaded(char " << int(i1) << ')'; } -#if ENABLE_TEST_OF_OVERLOADED_FUNCTIONS void foo_overloaded(short i1) { result_stream << "test::foo_overloaded(short " << (int)i1 << ')'; } -#endif double foo_overloaded(int i1, int i2) { @@ -58,105 +43,143 @@ struct test } // end anonymous namespace -int main(int argc, char* argv[]) +void +test_non_const() { - auto util = TestUtilities::get_instance(); + test t; + sigc::mem_fun (&test::foo)(t, 1); + util->check_result(result_stream, "test::foo(short 1)"); +} - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +void +test_const() +{ + test t; + sigc::mem_fun (&test::foo_const)(t, 2); + util->check_result(result_stream, "test::foo_const(int 2)"); +} - { /* test non-const */ - test t; - sigc::mem_fun(&test::foo)(t, 1); // on reference - util->check_result(result_stream, "test::foo(short 1)"); +void +test_const_with_const_object() +{ + const auto t = test(); + sigc::mem_fun (&test::foo_const)(t, 3); + util->check_result(result_stream, "test::foo_const(int 3)"); +} - sigc::mem_fun(&test::foo)(&t, 1); // on pointer - util->check_result(result_stream, "test::foo(short 1)"); - } - { /* test const */ - test t; - sigc::mem_fun(&test::foo_const)(t, 2); - util->check_result(result_stream, "test::foo_const(int 2)"); +void +test_non_const_volatile() +{ + test t; + sigc::mem_fun (&test::foo_volatile)(t, 4); + util->check_result(result_stream, "test::foo_volatile(float 4)"); +} - sigc::mem_fun(&test::foo_const)(&t, 2); - util->check_result(result_stream, "test::foo_const(int 2)"); - } - { /* test const with const object */ - const auto t = test(); - sigc::mem_fun(&test::foo_const)(t, 3); - util->check_result(result_stream, "test::foo_const(int 3)"); +void +test_const_volatile() +{ + test t; + sigc::mem_fun (&test::foo_const_volatile)(t, 5); + util->check_result(result_stream, "test::foo_const_volatile(double 5)"); +} - sigc::mem_fun(&test::foo_const)(&t, 3); - util->check_result(result_stream, "test::foo_const(int 3)"); - } - { /* test non-const volatile */ - test t; - sigc::mem_fun(&test::foo_volatile)(t, 4); // on reference - util->check_result(result_stream, "test::foo_volatile(float 4)"); +void +test_const_volatile_with_const_object() +{ + const auto t = test(); + sigc::mem_fun (&test::foo_const_volatile)(t, 6); + util->check_result(result_stream, "test::foo_const_volatile(double 6)"); +} - sigc::mem_fun(&test::foo_volatile)(&t, 4); // on pointer - util->check_result(result_stream, "test::foo_volatile(float 4)"); - } - { /* test const volatile */ - test t; - sigc::mem_fun(&test::foo_const_volatile)(t, 5); // on reference - util->check_result(result_stream, "test::foo_const_volatile(double 5)"); +void +test_overloaded() +{ + test t; - sigc::mem_fun(&test::foo_const_volatile)(&t, 5); // on pointer - util->check_result(result_stream, "test::foo_const_volatile(double 5)"); - } - { /* test const volatile with const object */ - const auto t = test(); - sigc::mem_fun(&test::foo_const_volatile)(t, 6); // on reference - util->check_result(result_stream, "test::foo_const_volatile(double 6)"); + // We need to specify the types when using overloaded functions. - sigc::mem_fun(&test::foo_const_volatile)(&t, 6); // on pointer - util->check_result(result_stream, "test::foo_const_volatile(double 6)"); - } -#if ENABLE_TEST_OF_OVERLOADED_FUNCTIONS - { /* test overloaded */ - test t; - sigc::mem_fun1(&test::foo_overloaded)(&t, 7); - util->check_result(result_stream, "test::foo_overloaded(char 7)"); + sigc::mem_fun (&test::foo_overloaded)(t, 7); + util->check_result(result_stream, "test::foo_overloaded(char 7)"); - sigc::mem_fun1(&test::foo_overloaded)(&t, 7); - util->check_result(result_stream, "test::foo_overloaded(short 7)"); + sigc::mem_fun (&test::foo_overloaded)(t, 7); + util->check_result(result_stream, "test::foo_overloaded(short 7)"); - //sigc::mem_fun1(&test::foo_overloaded)(&t, 7); - //util->check_result(result_stream, "test::foo_overloaded(short 7)"); + sigc::mem_fun (&test::foo_overloaded)(t, 7, 8); + util->check_result(result_stream, "test::foo_overloaded(int 7, int 8)"); +} - sigc::mem_fun2(&test::foo_overloaded)(&t, 7, 8); - util->check_result(result_stream, "test::foo_overloaded(int 7, int 8)"); - } -#endif - { /* test bound */ - test t; - sigc::mem_fun(t, &test::foo)(9); - util->check_result(result_stream, "test::foo(short 9)"); +void +test_bound() +{ + test t; + sigc::mem_fun(t, &test::foo)(9); + util->check_result(result_stream, "test::foo(short 9)"); - sigc::mem_fun(&t, &test::foo)(9); - util->check_result(result_stream, "test::foo(short 9)"); + sigc::mem_fun(t, &test::foo)(9); + util->check_result(result_stream, "test::foo(short 9)"); - sigc::mem_fun(t, &test::foo_const)(9); - util->check_result(result_stream, "test::foo_const(int 9)"); + sigc::mem_fun(t, &test::foo_const)(9); + util->check_result(result_stream, "test::foo_const(int 9)"); - sigc::mem_fun(&t, &test::foo_const)(9); - util->check_result(result_stream, "test::foo_const(int 9)"); + sigc::mem_fun(t, &test::foo_const)(9); + util->check_result(result_stream, "test::foo_const(int 9)"); - sigc::mem_fun(t, &test::foo_volatile)(9); - util->check_result(result_stream, "test::foo_volatile(float 9)"); + sigc::mem_fun(t, &test::foo_volatile)(9); + util->check_result(result_stream, "test::foo_volatile(float 9)"); - sigc::mem_fun(&t, &test::foo_volatile)(9); - util->check_result(result_stream, "test::foo_volatile(float 9)"); + sigc::mem_fun(t, &test::foo_volatile)(9); + util->check_result(result_stream, "test::foo_volatile(float 9)"); -#if ENABLE_TEST_OF_OVERLOADED_FUNCTIONS - sigc::mem_fun2(t, &test::foo_overloaded)(9, 10); - util->check_result(result_stream, "test::foo_overloaded(int 9, int 10)"); + sigc::mem_fun(t, &test::foo_overloaded)(9, 10); + util->check_result(result_stream, "test::foo_overloaded(int 9, int 10)"); +} + +class TestAutoDisconnect : public sigc::trackable +{ +public: + void foo() { result_stream << "TestAutoDisconnect::foo() called."; } +}; + +void +test_auto_disconnect() +{ + // Check that slot doesn't try to call a method on a destroyed instance, + // when the instance's class derives from trackable. + sigc::slot slot_of_member_method; + { + TestAutoDisconnect t; + slot_of_member_method = sigc::mem_fun(t, &TestAutoDisconnect::foo); - sigc::mem_fun2(&t, &test::foo_overloaded)(9, 10); - util->check_result(result_stream, "test::foo_overloaded(int 9, int 10)"); -#endif + // The method should be called: + slot_of_member_method(); + util->check_result(result_stream, "TestAutoDisconnect::foo() called."); } + // The method should not be called: + slot_of_member_method(); + util->check_result(result_stream, ""); +} + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_non_const(); + test_const(); + test_const_with_const_object(); + test_non_const_volatile(); + test_const_volatile(); + test_const_volatile_with_const_object(); + + test_overloaded(); + + test_bound(); + + test_auto_disconnect(); + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_member_method_trait.cc b/tests/test_member_method_trait.cc new file mode 100644 index 00000000..bc5c4502 --- /dev/null +++ b/tests/test_member_method_trait.cc @@ -0,0 +1,101 @@ +/* Copyright 2016 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include +#include +#include + +namespace +{ + +class Something +{ +public: + void some_func(int) {} + + void some_const_func(int) const {} + + void some_volatile_func(int) volatile {} + + void some_const_volatile_func(int) const volatile {} + + int some_int_func() { return 1; } + + bool some_bool_func() { return true; } +}; + +} // end anonymous namespace + +void +test_member_method_is_const() +{ + static_assert(!sigc::internal::member_method_is_const::value, + "member_method_is_const failed to identify a non-const member method."); + + static_assert( + !sigc::internal::member_method_is_const::value, + "member_method_is_const failed to identify a non-const member method."); + + static_assert( + sigc::internal::member_method_is_const::value, + "member_method_is_const failed to identify a const member method."); + + static_assert( + sigc::internal::member_method_is_const::value, + "member_method_is_const failed to identify a const member method."); +} + +void +test_member_method_is_volatile() +{ + static_assert(!sigc::internal::member_method_is_volatile::value, + "member_method_is_const failed to identify a non-volatile member method."); + + static_assert( + !sigc::internal::member_method_is_volatile::value, + "member_method_is_const failed to identify a non-volatile member method."); + + static_assert( + sigc::internal::member_method_is_volatile::value, + "member_method_is_const failed to identify a volatile member method."); + + static_assert(sigc::internal::member_method_is_volatile< + decltype(&Something::some_const_volatile_func)>::value, + "member_method_is_const failed to identify a volatile member method."); +} + +void +test_member_method_class_type() +{ + static_assert( + std::is_same::type, + Something>::value, + "member_method_class_type failed to identify the class type."); +} + +void +test_member_method_result_type() +{ + static_assert( + std::is_same::type, + int>::value, + "member_method_result_type failed to identify the result type."); + + static_assert( + std::is_same::type, + bool>::value, + "member_method_result_type failed to identify the result type."); +} + +int +main() +{ + test_member_method_is_const(); + test_member_method_is_volatile(); + + test_member_method_class_type(); + test_member_method_result_type(); + + return EXIT_SUCCESS; +} diff --git a/tests/test_ptr_fun.cc b/tests/test_ptr_fun.cc index d3cbf51d..6c29437b 100644 --- a/tests/test_ptr_fun.cc +++ b/tests/test_ptr_fun.cc @@ -1,44 +1,47 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" -#include #include -#include - -//TODO: put something like #ifndef FORTE ... #else ... #endif around: -#define ENABLE_TEST_OF_OVERLOADED_FUNCTIONS 0 namespace { std::ostringstream result_stream; +// TODO: This works with clang++ (when we specify the return type, such as +// int or void, but doesn't work with g++. +/* int foo() { result_stream << "foo()"; return 1; } +*/ -void foo(int i1) +void +foo(int i1) { result_stream << "foo(int " << i1 << ")"; } -#if ENABLE_TEST_OF_OVERLOADED_FUNCTIONS -void bar(char i1) +void +bar(char i1) { result_stream << "bar(char " << (int)i1 << ")"; } -#endif -void bar(float i1) +// Note: This doesn't work with some older versions of g++, +// even when we specify the return type. +// Hopefully those g++ versions are old enough now. +void +bar(float i1) { result_stream << "bar(float " << i1 << ")"; } -double bar(int i1, int i2) +double +bar(int i1, int i2) { result_stream << "bar(int " << i1 << ", int " << i2 << ")"; return 1.0f; @@ -46,42 +49,44 @@ double bar(int i1, int i2) struct test { - static void foo() - { - result_stream << "test::foo()"; - } + static void foo() { result_stream << "test::foo()"; } }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::ptr_fun0(&foo)(); - util->check_result(result_stream, "foo()"); + // Test use of overloaded functions that differ by number of parameters + // and by return type + // TODO: This works with clang++ (when we specify the return type, such as + // int or void, but doesn't work with g++. + // sigc::ptr_fun(&foo)(); + // util->check_result(result_stream, "foo()"); - sigc::ptr_fun1(&foo)(1); + sigc::ptr_fun (&foo)(1); util->check_result(result_stream, "foo(int 1)"); -#if ENABLE_TEST_OF_OVERLOADED_FUNCTIONS - sigc::ptr_fun1(&bar)(2); + // Test use of overloaded functions that differ by parameter type: + sigc::ptr_fun (&bar)(2); util->check_result(result_stream, "bar(char 2)"); - sigc::ptr_fun1(&bar)(2.0f); - util->check_result(result_stream, "bar(float 2)"); -#else - sigc::ptr_fun1(&bar)(2.0f); + sigc::ptr_fun (&bar)(2.0f); util->check_result(result_stream, "bar(float 2)"); -#endif - sigc::ptr_fun2(&bar)(3, 5); + // int or void, but doesn't work with g++. + // sigc::ptr_fun(&bar)(2.0f); + // util->check_result(result_stream, "bar(float 2)"); + + sigc::ptr_fun (&bar)(3, 5); util->check_result(result_stream, "bar(int 3, int 5)"); - sigc::ptr_fun(&test::foo)(); + sigc::ptr_fun (&test::foo)(); util->check_result(result_stream, "test::foo()"); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/test_retype.cc b/tests/test_retype.cc index 848731f5..7376bf87 100644 --- a/tests/test_retype.cc +++ b/tests/test_retype.cc @@ -1,15 +1,14 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include namespace { + +TestUtilities* util = nullptr; std::ostringstream result_stream; struct foo : public sigc::trackable @@ -27,45 +26,90 @@ struct foo : public sigc::trackable } }; -void bar(short s) +void +bar(short s) { result_stream << "bar(short " << s << ")"; } -} // end anonymous namespace - -int main(int argc, char* argv[]) +void +test_member_int() { - auto util = TestUtilities::get_instance(); - - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - foo foo_; result_stream << sigc::retype(sigc::mem_fun(foo_, &foo::test_int))(1.234f); util->check_result(result_stream, "foo::test_int(int 1) 1.5"); +} +void +test_member_float() +{ + foo foo_; result_stream << sigc::retype(sigc::mem_fun(foo_, &foo::test_float))(5); util->check_result(result_stream, "foo::test_float(float 5) 25"); +} +void +test_ptr_fun() +{ sigc::retype(sigc::ptr_fun(&bar))(6.789f); util->check_result(result_stream, "bar(short 6)"); +} - sigc::slot s1 = sigc::retype(sigc::mem_fun(foo_, &foo::test_int)); - sigc::slot s2 = sigc::retype(sigc::mem_fun(foo_, &foo::test_float)); - sigc::slot s3 = sigc::retype(sigc::ptr_fun(&bar)); +void +test_member_int_with_slot() +{ + foo foo_; + sigc::slot s1 = sigc::retype(sigc::mem_fun(foo_, &foo::test_int)); result_stream << s1(1.234f); util->check_result(result_stream, "foo::test_int(int 1) 1.5"); +} +void +test_member_float_with_slot() +{ + foo foo_; + sigc::slot s2 = sigc::retype(sigc::mem_fun(foo_, &foo::test_float)); result_stream << s2(5); util->check_result(result_stream, "foo::test_float(float 5) 25"); +} +void +test_ptr_fun_with_slot() +{ + sigc::slot s3 = sigc::retype(sigc::ptr_fun(&bar)); s3(6.789); util->check_result(result_stream, "bar(short 6)"); +} - s2 = sigc::retype(s1); +void +test_retype_slot() +{ + foo foo_; + sigc::slot s1 = sigc::retype(sigc::mem_fun(foo_, &foo::test_int)); + sigc::slot s2 = sigc::retype(s1); result_stream << s2(5); util->check_result(result_stream, "foo::test_int(int 5) 7.5"); +} + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_member_int(); + test_member_float(); + test_ptr_fun(); + + test_member_int_with_slot(); + test_member_float_with_slot(); + test_ptr_fun_with_slot(); + + test_retype_slot(); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_retype_return.cc b/tests/test_retype_return.cc index 9026e326..ded28239 100644 --- a/tests/test_retype_return.cc +++ b/tests/test_retype_return.cc @@ -1,22 +1,17 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include namespace { std::ostringstream result_stream; -struct foo : public sigc::functor_base +struct foo { - typedef float result_type; - float operator()(int i) { result_stream << "foo(int " << i << ") "; @@ -30,10 +25,8 @@ struct foo : public sigc::functor_base } }; -struct bar : public sigc::trackable, public sigc::functor_base +struct bar : public sigc::trackable { - typedef int result_type; - int operator()(int i) { result_stream << "bar(int " << i << ")"; @@ -43,7 +36,8 @@ struct bar : public sigc::trackable, public sigc::functor_base } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -55,7 +49,7 @@ int main(int argc, char* argv[]) util->check_result(result_stream, "foo(float 1.234) 6"); // retype_return / hide_return - sigc::slot sl; + sigc::slot sl; sl = sigc::retype_return(bar()); sl(5); util->check_result(result_stream, "bar(int 5)"); diff --git a/tests/test_rvalue_ref.cc b/tests/test_rvalue_ref.cc new file mode 100644 index 00000000..344a8563 --- /dev/null +++ b/tests/test_rvalue_ref.cc @@ -0,0 +1,100 @@ +#include "testutilities.h" +#include +#include + +struct MoveableStruct +{ +}; + +namespace +{ +TestUtilities* util = nullptr; +std::ostringstream result_stream; + +struct foo +{ + void operator()(MoveableStruct&& /* x */) { result_stream << "foo(MoveableStruct&&)"; } +}; + +struct A +{ + void foo(MoveableStruct&&) { result_stream << "A::foo(MoveableStruct&&)"; } +}; + +void +boo(MoveableStruct&&) +{ + result_stream << "boo(MoveableStruct&&)"; +} + +} // end anonymous namespace + +void +test_signal() +{ + sigc::signal signal; + foo f; + signal.connect(f); + MoveableStruct x; + signal(std::move(x)); + util->check_result(result_stream, "foo(MoveableStruct&&)"); +} + +void +test_slot() +{ + sigc::slot slot; + foo f; + slot = f; + MoveableStruct x; + slot(std::move(x)); + util->check_result(result_stream, "foo(MoveableStruct&&)"); +} + +void +test_mem_fun() +{ + sigc::slot slot; + A a; + slot = sigc::mem_fun(&A::foo); + MoveableStruct x; + slot(a, std::move(x)); + util->check_result(result_stream, "A::foo(MoveableStruct&&)"); +} + +void +test_bound_mem_fun() +{ + sigc::slot slot; + A a; + slot = sigc::mem_fun(a, &A::foo); + MoveableStruct x; + slot(std::move(x)); + util->check_result(result_stream, "A::foo(MoveableStruct&&)"); +} + +void +test_ptr_fun() +{ + sigc::slot slot; + slot = sigc::ptr_fun(&boo); + MoveableStruct x; + slot(std::move(x)); + util->check_result(result_stream, "boo(MoveableStruct&&)"); +} + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_signal(); + test_slot(); + test_bound_mem_fun(); + test_mem_fun(); + test_ptr_fun(); + + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +} // end main() diff --git a/tests/test_scoped_connection.cc b/tests/test_scoped_connection.cc new file mode 100644 index 00000000..520197fc --- /dev/null +++ b/tests/test_scoped_connection.cc @@ -0,0 +1,214 @@ +/* Copyright 2023, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include "testutilities.h" +#include +#include +#include +#include +#include + +// Test the expected special members and conversions, esp. NOT copyable BUT movable. +static_assert( std::is_nothrow_default_constructible_v); +static_assert(!std::is_copy_constructible_v ); +static_assert(!std::is_copy_assignable_v ); +static_assert( std::is_nothrow_move_constructible_v ); +static_assert( std::is_move_assignable_v ); +static_assert( std::is_nothrow_swappable_v ); +// TODO: C++20: Test the stronger std::is_nothrow_convertible_v; it should pass. +static_assert( std::is_convertible_v); +static_assert(!std::is_convertible_v); +static_assert( std::is_assignable_v ); +static_assert(!std::is_assignable_v ); + +namespace +{ +std::ostringstream result_stream; + +int +foo(int i) +{ + result_stream << "foo(" << i << ") "; + return 1; +} + +int +bar(double i) +{ + result_stream << "bar(" << i << ") "; + return 1; +} + +struct A : public sigc::trackable +{ + int foo(int i) + { + result_stream << "A::foo(" << i << ") "; + return 1; + } +}; + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + auto util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + sigc::signal sig; + sigc::connection confoo; + sigc::connection conbar; + sigc::connection cona; + + { + A a; + sig.connect(sigc::mem_fun(a, &A::foo)); + conbar = sig.connect(&bar); + confoo = sig.connect_first(&foo); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(1); + util->check_result( + result_stream, "sig is connected to (size=3): foo(1) A::foo(1) bar(1) "); + } + // normal connections are still connected. mem_fun disconnected via trackable. + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(2); + util->check_result(result_stream, "sig is connected to (size=2): foo(2) bar(2) "); + + { + A a; + sig.connect(sigc::mem_fun(a, &A::foo)); + sigc::scoped_connection sconfoo = sig.connect(&foo); + sigc::scoped_connection sconbar = sig.connect_first(&bar); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(3); + util->check_result( + result_stream, "sig is connected to (size=5): bar(3) foo(3) bar(3) A::foo(3) foo(3) "); + } + // scoped connections are now disconnected. + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(4); + util->check_result(result_stream, "sig is connected to (size=2): foo(4) bar(4) "); + + // copying connection to a scoped connection disconnects when latter destroyed + // copy-constructor: + { + sigc::scoped_connection sconfoo = confoo; + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(5); + util->check_result( + result_stream, "sig is connected to (size=2): foo(5) bar(5) "); + } + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(6); + util->check_result( + result_stream, "sig is connected to (size=1): bar(6) "); + // copy-assignment: + confoo = sig.connect(&foo); + { + sigc::scoped_connection sconfoo = sig.connect(&bar); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(7); + util->check_result( + result_stream, "sig is connected to (size=3): bar(7) foo(7) bar(7) "); + // copy-assignment disconnects currently held connection & replaces with new + sconfoo = confoo; + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(8); + util->check_result( + result_stream, "sig is connected to (size=2): bar(8) foo(8) "); + } + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(9); + util->check_result( + result_stream, "sig is connected to (size=1): bar(9) "); + + // moving scoped_connection transfers ownership/disconnection to destination + // move-constructor: + { + auto src = std::make_unique(sig.connect(&foo)); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(10); + util->check_result( + result_stream, "sig is connected to (size=2): bar(10) foo(10) "); + + sigc::scoped_connection dst = std::move(*src); + src.reset(); // This will NOT disconnect from foo() + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(11); + util->check_result( + result_stream, "sig is connected to (size=2): bar(11) foo(11) "); + } + + // move-assignment: + { + auto src = std::make_unique(sig.connect(&foo)); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(12); + util->check_result( + result_stream, "sig is connected to (size=2): bar(12) foo(12) "); + + sigc::scoped_connection dst; + dst = std::move(*src); + src.reset(); // This will NOT disconnect from foo() + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(13); + util->check_result( + result_stream, "sig is connected to (size=2): bar(13) foo(13) "); + } + + // dst from above is now destroyed + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(14); + util->check_result( + result_stream, "sig is connected to (size=1): bar(14) "); + + // swap + sigc::scoped_connection sconfoo = sig.connect(&foo); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(15); + util->check_result( + result_stream, "sig is connected to (size=2): bar(15) foo(15) "); + sigc::scoped_connection sconbar = sig.connect(&bar); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(16); + util->check_result( + result_stream, "sig is connected to (size=3): bar(16) foo(16) bar(16) "); + swap(sconbar, sconfoo); + // disconnect sconbar, which was swapped to refer to &foo + sconbar.disconnect(); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(17); + util->check_result( + result_stream, "sig is connected to (size=2): bar(17) bar(17) "); + + // manual disconnection + sconfoo.disconnect(); // was swapped to refer to 2nd &bar + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(18); + util->check_result( + result_stream, "sig is connected to (size=1): bar(18) "); + + // release + sconfoo = sig.connect(&foo); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(19); + util->check_result( + result_stream, "sig is connected to (size=2): bar(19) foo(19) "); + sigc::connection rconfoo = sconfoo.release(); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(20); + util->check_result( + result_stream, "sig is connected to (size=2): bar(20) foo(20) "); + rconfoo.disconnect(); + result_stream << "sig is connected to (size=" << sig.size() << "): "; + sig(21); + util->check_result( + result_stream, "sig is connected to (size=1): bar(21) "); + + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/test_signal.cc b/tests/test_signal.cc index 163eb113..a7650dd8 100644 --- a/tests/test_signal.cc +++ b/tests/test_signal.cc @@ -1,32 +1,25 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include -#include -#include +#include namespace { + +TestUtilities* util = nullptr; std::ostringstream result_stream; -int foo(int i) +int +foo(int i) { result_stream << "foo(int " << i << ") "; return 1; } -int bar(float i) -{ - result_stream << "bar(float " << i << ") "; - return 1; -} - struct A : public sigc::trackable { int foo(int i) @@ -42,53 +35,148 @@ struct A : public sigc::trackable } }; -} // end anonymous namespace - -int main(int argc, char* argv[]) +void +test_empty_signal() { - auto util = TestUtilities::get_instance(); - - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - // signal - sigc::signal sig; + sigc::signal sig; // emit empty signal sig(0); util->check_result(result_stream, ""); +} + +void +test_simple() +{ + sigc::signal sig; + sig.connect([](int i) { return foo(i); }); + + sig(1); + util->check_result(result_stream, "foo(int 1) "); +} + +int +bar(float i) +{ + result_stream << "bar(float " << i << ") "; + return 1; +} + +template +void +test_auto_disconnection() +{ + // signal + T_signal sig; // connect some slots before emitting & test auto-disconnection { A a; - sig.connect(sigc::ptr_fun1(&foo)); - sig.connect(sigc::mem_fun1(&a, &A::foo)); - sig.connect(sigc::ptr_fun1(&bar)); + sig.connect(sigc::ptr_fun(&foo)); + sig.connect_first(sigc::mem_fun(a, &A::foo)); + sig.connect_first(sigc::ptr_fun(&bar)); sig(1); result_stream << sig.size(); - util->check_result(result_stream, "foo(int 1) A::foo(int 1) bar(float 1) 3"); + util->check_result(result_stream, "bar(float 1) A::foo(int 1) foo(int 1) 3"); } // a dies => auto-disconnect sig(2); result_stream << sig.size(); - util->check_result(result_stream, "foo(int 2) bar(float 2) 2"); + util->check_result(result_stream, "bar(float 2) foo(int 2) 2"); +} +void +test_reference() +{ // test reference A a; std::string str("guest book"); - sigc::signal sigstr; - sigstr.connect(sigc::mem_fun(&a, &A::bar)); + sigc::signal sigstr; + sigstr.connect(sigc::mem_fun(a, &A::bar)); sigstr(str); result_stream << str; util->check_result(result_stream, "A::foo(string 'guest book') foo was here"); +} +void +test_make_slot() +{ // test make_slot() - sig.connect(sigc::ptr_fun1(&foo)); - sigc::signal sig2; + sigc::signal sig; + sig.connect(sigc::ptr_fun(&foo)); + sig.connect_first([](float i) { return bar(i); }); + sig.connect(sigc::ptr_fun(&foo)); + sigc::signal sig2; sig2.connect(sig.make_slot()); sig2(3); - util->check_result(result_stream, "foo(int 3) bar(float 3) foo(int 3) "); + util->check_result(result_stream, "bar(float 3) foo(int 3) foo(int 3) "); + + // Delete a trackable_signal that has been connected to sig2. + sig2.clear(); + sig2.connect(sigc::ptr_fun(&bar)); + auto sig3 = std::make_unique>(); + sig3->connect(sigc::ptr_fun(&foo)); + sig2.connect(sig3->make_slot()); + sig2(2); + sig3.reset(); + sig2(42); + util->check_result(result_stream, "bar(float 2) foo(int 2) bar(float 42) "); +} + +void +test_clear_called_in_signal_handler() +{ + sigc::signal sig; + sig.connect([]() { result_stream << ", slot 1, "; }); + sig.connect( + [&sig]() + { + sig.clear(); + result_stream << "slot 2, "; + }); + sig.connect([]() { result_stream << "slot 3, "; }); + result_stream << sig.size(); + sig.emit(); + result_stream << sig.size(); + sig.emit(); + util->check_result(result_stream, "3, slot 1, slot 2, 0"); +} + +void +test_clear_called_outside_signal_handler() +{ + sigc::signal sig; + sig.connect([]() { result_stream << ", slot 1, "; }); + sig.connect([]() { result_stream << "slot 2, "; }); + sig.connect([]() { result_stream << "slot 3, "; }); + result_stream << sig.size(); + sig.emit(); + sig.clear(); + result_stream << sig.size(); + sig.emit(); + util->check_result(result_stream, "3, slot 1, slot 2, slot 3, 0"); +} + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_empty_signal(); + test_simple(); + test_auto_disconnection>(); + test_auto_disconnection>(); + test_reference(); + test_make_slot(); + test_clear_called_in_signal_handler(); + test_clear_called_outside_signal_handler(); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_signal_connect.cc b/tests/test_signal_connect.cc new file mode 100644 index 00000000..ef4e1045 --- /dev/null +++ b/tests/test_signal_connect.cc @@ -0,0 +1,121 @@ +/* Copyright 2024, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include "testutilities.h" +#include +#include + +namespace +{ + +TestUtilities* util = nullptr; +std::ostringstream result_stream; + +void +fun(int i) +{ + result_stream << "fun(int " << i << ")"; +} + +[[maybe_unused]] +void +fun(double d) +{ + result_stream << "fun(double " << d << ")"; +} + +struct foo : public sigc::trackable +{ + void fun_nonconst(int i) + { + result_stream << "foo::fun_nonconst(int " << i << ")"; + } + + void fun_nonconst(double d) + { + result_stream << "foo::fun_nonconst(double " << d << ")"; + } + + void fun_const(int i) const + { + result_stream << "foo::fun_const(int " << i << ")"; + } + + void fun_const(double d) const + { + result_stream << "foo::fun_const(double " << d << ")"; + } +}; + +void +test_signal_connect_fun() +{ + sigc::signal signal; + + sigc::signal_connect(signal, &fun); + + signal.emit(42); + util->check_result(result_stream, "fun(int 42)"); +} + +void +test_signal_connect_method_nonconst() +{ + sigc::signal signal; + foo f; + + sigc::signal_connect(signal, f, &foo::fun_nonconst); + + signal.emit(42); + util->check_result(result_stream, "foo::fun_nonconst(int 42)"); +} + +void +test_signal_connect_method_const() +{ + sigc::signal signal; + foo f; + + sigc::signal_connect(signal, f, &foo::fun_const); + + signal.emit(42); + util->check_result(result_stream, "foo::fun_const(int 42)"); +} + +void +test_signal_connect_method_const_with_const_object() +{ + sigc::signal signal; + const foo f; + + sigc::signal_connect(signal, f, &foo::fun_const); + + signal.emit(42); + util->check_result(result_stream, "foo::fun_const(int 42)"); +} + +void +test_signal_connect_method() +{ + test_signal_connect_method_nonconst(); + test_signal_connect_method_const(); + test_signal_connect_method_const_with_const_object(); +} + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_signal_connect_fun(); + + test_signal_connect_method(); + + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/test_signal_move.cc b/tests/test_signal_move.cc index 6365e5bd..83a6316d 100644 --- a/tests/test_signal_move.cc +++ b/tests/test_signal_move.cc @@ -1,20 +1,17 @@ -/* Copyright 2015, The libsigc++ Development Team +/* Copyright 2015 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include -#include -#include -#include namespace { std::ostringstream result_stream; -int foo(int i) +int +foo(int i) { result_stream << "foo(int " << i << ")"; return 1; @@ -22,7 +19,8 @@ int foo(int i) } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -30,21 +28,21 @@ int main(int argc, char* argv[]) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; // signal - sigc::signal sig; + sigc::signal sig; sig.connect(sigc::ptr_fun(&foo)); sig(1); util->check_result(result_stream, "foo(int 1)"); - //Test the move constructor: - sigc::signal sig2(std::move(sig)); - sig(-2); + // Test the move constructor: + sigc::signal sig2(std::move(sig)); + sig(-2); // Test that the moved-from slot does nothing. sig2(2); util->check_result(result_stream, "foo(int 2)"); - //Test the move assignment operator: - sigc::signal sig3; + // Test the move assignment operator: + sigc::signal sig3; sig3 = std::move(sig2); - sig2(-3); + sig2(-3); // Test that the moved-from slot does nothing. sig3(3); util->check_result(result_stream, "foo(int 3)"); diff --git a/tests/test_size.cc b/tests/test_size.cc index c9024621..4b09a253 100644 --- a/tests/test_size.cc +++ b/tests/test_size.cc @@ -1,12 +1,10 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include #include -#include // The correct result of this test may be implementation-dependent. // No attempt is made to decide if the result is correct. @@ -17,11 +15,12 @@ namespace { struct A { - void foo(); + void foo() {} }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -32,19 +31,46 @@ int main(int argc, char* argv[]) { std::cout << "sizes of public classes:" << std::endl; + // libsigc++ 2.10: 8 + // libsigc++ 3.0: 8 std::cout << " trackable: " << sizeof(sigc::trackable) << std::endl; - std::cout << " slot: " << sizeof(sigc::slot) << std::endl; - std::cout << " signal: " << sizeof(sigc::signal) << std::endl; - std::cout << " signal::iterator: " << sizeof(sigc::signal::iterator) << std::endl; + + // libsigc++ 2.10: 16 + // libsigc++ 3.0: 16 + std::cout << " slot: " << sizeof(sigc::slot) << std::endl; + + // libsigc++ 2.10: 16 + // libsigc++ 3.0: 16 + std::cout << " signal: " << sizeof(sigc::signal) << std::endl; + + // libsigc++ 2.10: 8 + // libsigc++ 3.0: 8 std::cout << " connection: " << sizeof(sigc::connection) << std::endl; std::cout << std::endl << "sizes of internal classes:" << std::endl; - std::cout << " trackable_callback: " << sizeof(sigc::internal::trackable_callback) << std::endl; - std::cout << " trackable_callback_list: " << sizeof(sigc::internal::trackable_callback_list) << std::endl; + // libsigc++ 2.10: 16 + // libsigc++ 3.0: 16 + std::cout << " trackable_callback: " << sizeof(sigc::internal::trackable_callback) + << std::endl; + + // libsigc++ 2.10: 32 + // libsigc++ 3.0: 32 + std::cout << " trackable_callback_list: " << sizeof(sigc::internal::trackable_callback_list) + << std::endl; + + // libsigc++ 2.10: 48 + // libsigc++ 3.0: 48 std::cout << " slot_rep: " << sizeof(sigc::internal::slot_rep) << std::endl; - std::cout << " typed_slot_rep >: " - << sizeof(sigc::internal::typed_slot_rep >) << std::endl; + + // libsigc++ 2.10: 72 + // libsigc++ 3.0: 64 + std::cout << " typed_slot_rep >: " + << sizeof(sigc::internal::typed_slot_rep>) + << std::endl; + + // libsigc++ 2.10: 32 + // libsigc++ 3.0: 32 std::cout << " signal_impl: " << sizeof(sigc::internal::signal_impl) << std::endl; } return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; diff --git a/tests/test_slot.cc b/tests/test_slot.cc index 07b35806..7fd68bd8 100644 --- a/tests/test_slot.cc +++ b/tests/test_slot.cc @@ -1,84 +1,105 @@ -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include -#include -//The Tru64 compiler seems to need this to avoid an unresolved symbol -//See bug #161503 -#include +// The Tru64 compiler seems to need this to avoid an unresolved symbol +// See bug #161503 namespace { + +TestUtilities* util = nullptr; std::ostringstream result_stream; class foo { public: - void operator()(int i) - { - result_stream << "foo(int " << i << ")"; - } + void operator()(int i) { result_stream << "foo(int " << i << ")"; } void operator()(std::string& str) { result_stream << "foo(string '" << str << "') "; - str="foo was here"; + str = "foo was here"; } - void operator()(int, int) - { - result_stream << "foo(int, int)"; - } + void operator()(int, int) { result_stream << "foo(int, int)"; } }; -} // end anonymous namespace - -int main(int argc, char* argv[]) +void +test_simple() { - auto util = TestUtilities::get_instance(); - - if (!util->check_command_args(argc, argv)) - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - // simple test - sigc::slot s1 = foo(); + sigc::slot s1 = foo(); s1(1); util->check_result(result_stream, "foo(int 1)"); s1 = foo(); s1(2); util->check_result(result_stream, "foo(int 2)"); +} +void +test_implicit_conversion() +{ // test implicit conversion - sigc::slot s2 = foo(); + sigc::slot s2 = foo(); s2(3); util->check_result(result_stream, "foo(int 3)"); +} +void +test_reference() +{ // test reference - sigc::slot sl1 = foo(); + sigc::slot sl1 = foo(); std::string str("guest book"); sl1(str); result_stream << str; util->check_result(result_stream, "foo(string 'guest book') foo was here"); +} +void +test_operator_equals() +{ // test operator= - str = "guest book"; - sigc::slot sl2; + std::string str = "guest book"; + sigc::slot sl1 = foo(); + sigc::slot sl2; sl2 = sl1; sl1 = sl2; sl1(str); result_stream << str; util->check_result(result_stream, "foo(string 'guest book') foo was here"); +} +void +test_copy_ctor() +{ // test copy ctor - sigc::slot s1_clone(s1); + sigc::slot s1 = foo(); + sigc::slot s1_clone(s1); s1_clone(4); util->check_result(result_stream, "foo(int 4)"); +} + +} // end anonymous namespace + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_simple(); + test_implicit_conversion(); + test_reference(); + test_operator_equals(); + test_copy_ctor(); return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_slot_disconnect.cc b/tests/test_slot_disconnect.cc index 4044135d..e14cf99e 100644 --- a/tests/test_slot_disconnect.cc +++ b/tests/test_slot_disconnect.cc @@ -1,38 +1,38 @@ -/* Copyright 2005, The libsigc++ Development Team +/* Copyright 2005 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include -#include namespace { std::ostringstream result_stream; -void Foo() +void +Foo() { result_stream << "Foo"; } -void Bar() +void +Bar() { result_stream << "Bar"; } } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - //Note that sigc::ptr_fun() creates a sigc::pointer_functor0. - sigc::slot theSlot(sigc::ptr_fun(&Foo)); + // Note that sigc::ptr_fun() creates a sig::pointer_functor. + sigc::slot theSlot(sigc::ptr_fun(&Foo)); theSlot(); util->check_result(result_stream, "Foo"); @@ -44,7 +44,7 @@ int main(int argc, char* argv[]) theSlot(); util->check_result(result_stream, "Bar"); - theSlot = sigc::slot(); // Assign an empty slot. + theSlot = sigc::slot(); // Assign an empty slot. theSlot(); util->check_result(result_stream, ""); diff --git a/tests/test_slot_move.cc b/tests/test_slot_move.cc index 06975f51..d207172c 100644 --- a/tests/test_slot_move.cc +++ b/tests/test_slot_move.cc @@ -1,16 +1,12 @@ -/* Copyright 2015, The libsigc++ Development Team +/* Copyright 2015 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" #include -#include -#include -#include -//The Tru64 compiler seems to need this to avoid an unresolved symbol -//See bug #161503 -#include +// The Tru64 compiler seems to need this to avoid an unresolved symbol +// See bug #161503 namespace { @@ -19,26 +15,21 @@ std::ostringstream result_stream; class foo { public: - void operator()(int i) - { - result_stream << "foo(int " << i << ")"; - } + void operator()(int i) { result_stream << "foo(int " << i << ")"; } void operator()(std::string& str) { result_stream << "foo(string '" << str << "') "; - str="foo was here"; + str = "foo was here"; } - void operator()(int, int) - { - result_stream << "foo(int, int)"; - } + void operator()(int, int) { result_stream << "foo(int, int)"; } }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); @@ -46,20 +37,20 @@ int main(int argc, char* argv[]) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; // simple test - sigc::slot s1 = foo(); + sigc::slot s1 = foo(); s1(1); util->check_result(result_stream, "foo(int 1)"); // test move constructor: - sigc::slot s2(std::move(s1)); - s1(-2); + sigc::slot s2(std::move(s1)); + s1(-2); // Test that the moved-from slot does nothing. s2(2); util->check_result(result_stream, "foo(int 2)"); // test move assignment: - sigc::slot s3; + sigc::slot s3; s3 = std::move(s2); - s2(-3); + s2(-3); // Test that the moved-from slot does nothing. s3(3); util->check_result(result_stream, "foo(int 3)"); diff --git a/tests/test_track_obj.cc b/tests/test_track_obj.cc index a6ce6edf..5d919534 100644 --- a/tests/test_track_obj.cc +++ b/tests/test_track_obj.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2013 The libsigc++ Development Team +/* Copyright (C) 2013 - 2016, The libsigc++ Development Team * * This file is part of libsigc++. * @@ -17,32 +17,28 @@ */ // The purpose of this test case is threefold. -// - Test sigc::track_obj(). +// - Test sigc::track_obj() and sigc::track_object(). // - Show that a slot with a C++11 lambda expression can be automatically // disconnected when an object derived from sigc::trackable is deleted, -// provided sigc::track_obj() is used. -// It's shown here as a preparation for deprecating and eventually -// deleting the libsigc++ lambda expressions. +// provided sigc::track_obj() or sigc::track_object() is used. +// It shows that C++11 lambda expressions can replace the libsigc++ lambda +// expressions, which have been removed. // See https://bugzilla.gnome.org/show_bug.cgi?id=672555 // - Test the code example in the documentation in sigc++/adaptors/track_obj.h. // -// To test the C++11 lambda expressions with gcc 4.6.3 (and probably some later -// versions of gcc; gcc 4.7.x also understands -std=c++11): -// make CXXFLAGS='-g -O2 -std=c++0x' test_track_obj -// ./test_track_obj -// echo $? // If test_track_obj writes nothing and the return code is 0, the test has passed. +// sigc::track_obj() is deprecated, but let's keep the test if possible. +// If libsigc++ is configured with -Dbuild-deprecated-api=false +// (--disable-deprecated-api), SIGCXX_DISABLE_DEPRECATED is defined in +// sigc++config.h. An undef at the start of this file has no effect. +#undef SIGCXX_DISABLE_DEPRECATED #include "testutilities.h" -#include #include -#include -#include #include #include - namespace { std::ostringstream result_stream; @@ -50,8 +46,8 @@ std::ostringstream result_stream; struct book : public sigc::trackable { explicit book(const std::string& name) : name_(name) {} - operator std::string& () { return name_; } - operator const std::string& () const { return name_; } + operator std::string&() { return name_; } + operator const std::string&() const { return name_; } std::string name_; }; @@ -59,156 +55,190 @@ struct bar_group4 : public sigc::trackable { }; -class Functor1 : public sigc::functor_base +class Functor1 { public: - typedef std::string result_type; + explicit Functor1(const bar_group4& bar) : bar_(bar) {} - Functor1(const bar_group4& bar) - : bar_(bar) {} + std::string operator()(int i) { return (i < 0) ? "negative" : ((i > 0) ? "positive" : "zero"); } - std::string operator()(int i) - { - return (i<0) ? "negative" : ((i>0) ? "positive" : "zero"); - } - -private: +protected: + // Don't make it private. clang++ does not like unused private data. const bar_group4& bar_; }; -class Functor2 : public sigc::functor_base +class Functor2 { public: - typedef std::string result_type; - - Functor2(const bar_group4& bar, const book& aBook) - : bar_(bar), aBook_(aBook) {} + Functor2(const bar_group4& bar, const book& aBook) : bar_(bar), aBook_(aBook) {} std::string operator()(int i, const std::string& str) const { - std::string result = (i<0) ? "negative, " : ((i>0) ? "positive, " : "zero, "); + std::string result = (i < 0) ? "negative, " : ((i > 0) ? "positive, " : "zero, "); result += str; result += aBook_; return result; } -private: +protected: + // Don't make it private. clang++ does not like unused private data. const bar_group4& bar_; + +private: const book& aBook_; }; -//C++11 lamba expressions: +// C++11 lamba expressions: -inline std::ostringstream& operator << (std::ostringstream& s, const book& b) +inline std::ostringstream& +operator<<(std::ostringstream& s, const book& b) { s << b.name_; return s; } -void egon(std::string& str) +void +egon(std::string& str) { result_stream << "egon(string '" << str << "')"; str = "egon was here"; } -void foo_group4(bar_group4&) +void +foo_group4(bar_group4&) { result_stream << "foo_group4(bar_group4&)"; } } // end anonymous namespace - -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::slot sl1; + sigc::slot sl1; + sigc::slot sl2; { bar_group4 bar4; +#ifndef SIGCXX_DISABLE_DEPRECATED sl1 = sigc::track_obj(Functor1(bar4), bar4); - result_stream << sl1(-2); - util->check_result(result_stream, "negative"); +#else + sl1 = sigc::track_object(Functor1(bar4), bar4); +#endif + sl2 = sigc::track_object(Functor1(bar4), bar4); + result_stream << sl1(-2) << ", " << sl2(2); + util->check_result(result_stream, "negative, positive"); - } // auto-disconnect sl1 + } // auto-disconnect sl1 and sl2 - result_stream << sl1(-2); - util->check_result(result_stream, ""); + result_stream << sl1(-2) << ", " << sl2(2); + util->check_result(result_stream, ", "); // Allocate on the heap. valgrind can then find erroneous memory accesses. // (There should be none, of course.) - auto psl2 = new sigc::slot; - bar_group4* pbar4 = new bar_group4; - book* pbook4 = new book("A Book"); - *psl2 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); - result_stream << (*psl2)(0, "Book title: "); - util->check_result(result_stream, "zero, Book title: A Book"); - - delete pbook4; // auto-disconnect *psl2 + auto psl3 = new sigc::slot; + auto psl4 = new sigc::slot; + auto pbar4 = new bar_group4; + auto pbook4 = new book("A Book"); +#ifndef SIGCXX_DISABLE_DEPRECATED + *psl3 = sigc::track_obj(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); +#else + *psl3 = sigc::track_object(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); +#endif + *psl4 = sigc::track_object(Functor2(*pbar4, *pbook4), *pbar4, *pbook4); + result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: "); + util->check_result(result_stream, "zero, Book title: A Book, positive, Title: A Book"); + + delete pbook4; // auto-disconnect *psl3 and *psl4 pbook4 = nullptr; - result_stream << (*psl2)(0, "Book title: "); - util->check_result(result_stream, ""); - delete psl2; - psl2 = nullptr; + result_stream << (*psl3)(0, "Book title: ") << ", " << (*psl4)(1, "Title: "); + util->check_result(result_stream, ", "); + delete psl3; + psl3 = nullptr; + delete psl4; + psl4 = nullptr; delete pbar4; pbar4 = nullptr; - -//C++11 lambda expressions: + // C++11 lambda expressions: // auto-disconnect // If you want to auto-disconnect a slot with a C++11 lambda expression // that contains references to sigc::trackable-derived objects, you must use - // sigc::track_obj(). - sigc::slot sl10; + // sigc::track_obj() or sigc::track_object(). + sigc::slot sl11; + sigc::slot sl12; { book guest_book("karl"); - // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; // no auto-disconnect - sl10 = sigc::track_obj([&guest_book](std::ostringstream& stream){ stream << guest_book; }, guest_book); - sl10(result_stream); - util->check_result(result_stream, "karl"); - - } // auto-disconnect sl10 - - sl10(result_stream); + // no auto-disconnect + // sl1 = [&guest_book](std::ostringstream& stream){ stream << guest_book << "\n"; }; +#ifndef SIGCXX_DISABLE_DEPRECATED + sl11 = sigc::track_obj( + [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); +#else + sl11 = sigc::track_object( + [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); +#endif + sl12 = sigc::track_object( + [&guest_book](std::ostringstream& stream) { stream << guest_book; }, guest_book); + sl11(result_stream); + sl12(result_stream); + util->check_result(result_stream, "karlkarl"); + + } // auto-disconnect sl11 and sl12 + + sl11(result_stream); + sl12(result_stream); util->check_result(result_stream, ""); // auto-disconnect - sigc::slot sl20; + sigc::slot sl21; + sigc::slot sl22; { book guest_book("karl"); // sl2 = [&guest_book] () { egon(guest_book); }; // no auto-disconnect // sl2 = std::bind(&egon, std::ref(guest_book)); // does not compile (gcc 4.6.3) - sl20 = sigc::track_obj([&guest_book] () { egon(guest_book); }, guest_book); - sl20(); - util->check_result(result_stream, "egon(string 'karl')"); +#ifndef SIGCXX_DISABLE_DEPRECATED + sl21 = sigc::track_obj([&guest_book]() { egon(guest_book); }, guest_book); +#else + sl21 = sigc::track_object([&guest_book]() { egon(guest_book); }, guest_book); +#endif + sl22 = sigc::track_object([&guest_book]() { egon(guest_book); }, guest_book); + sl21(); + sl22(); + util->check_result(result_stream, "egon(string 'karl')egon(string 'egon was here')"); result_stream << static_cast(guest_book); util->check_result(result_stream, "egon was here"); - } // auto-disconnect sl20 + } // auto-disconnect sl21 and sl22 - sl20(); + sl21(); + sl22(); util->check_result(result_stream, ""); - - // Code example in the documentation sigc++/adaptors/macros/track_obj.h.m4 - // ----------------------------------------------------------------------- + // Code example in the documentation sigc++/adaptors/track_obj.h. + // -------------------------------------------------------------- { - //struct bar : public sigc::trackable {} some_bar; - sigc::signal some_signal; + // struct bar : public sigc::trackable {} some_bar; + sigc::signal some_signal; { bar_group4 some_bar; - //some_signal.connect(sigc::group(&foo,sigc::ref(some_bar))); - // disconnected automatically if some_bar goes out of scope - //some_signal.connect([&some_bar](){ foo_group4(some_bar); }); // no auto-disconnect - //some_signal.connect(sigc::bind(&foo_group4, sigc::ref(some_bar))); // auto-disconnects, but we prefer C++11 lambda - some_signal.connect(sigc::track_obj([&some_bar](){ foo_group4(some_bar); }, some_bar)); + // some_signal.connect([&some_bar](){ foo_group4(some_bar); }); // no auto-disconnect + // some_signal.connect(sigc::bind(&foo_group4, std::ref(some_bar))); // auto-disconnects, + // but we prefer C++11 lambda +#ifndef SIGCXX_DISABLE_DEPRECATED + some_signal.connect(sigc::track_obj([&some_bar]() { foo_group4(some_bar); }, some_bar)); +#else + some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); +#endif + some_signal.connect(sigc::track_object([&some_bar]() { foo_group4(some_bar); }, some_bar)); some_signal.emit(); - util->check_result(result_stream, "foo_group4(bar_group4&)"); + util->check_result(result_stream, "foo_group4(bar_group4&)foo_group4(bar_group4&)"); } // auto-disconnect the lambda expression @@ -216,6 +246,5 @@ int main(int argc, char* argv[]) util->check_result(result_stream, ""); } - return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; } diff --git a/tests/test_trackable.cc b/tests/test_trackable.cc index 159aeeb2..bd48fe61 100644 --- a/tests/test_trackable.cc +++ b/tests/test_trackable.cc @@ -1,44 +1,38 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" -#include -#include #include #include -#include namespace { std::ostringstream result_stream; -class my_class: public sigc::trackable +class my_class : public sigc::trackable { public: - int i; + int i = 0; - void foo() - { - result_stream << i; - } + void foo() { result_stream << i; } }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::slot sl; + sigc::slot sl; { my_class t; t.i = 10; - sl = sigc::mem_fun0(&t, &my_class::foo); + sl = sigc::mem_fun(t, &my_class::foo); sl(); util->check_result(result_stream, "10"); } diff --git a/tests/test_trackable_move.cc b/tests/test_trackable_move.cc index 2d16273e..05a14b42 100644 --- a/tests/test_trackable_move.cc +++ b/tests/test_trackable_move.cc @@ -1,76 +1,65 @@ -// -*- c++ -*- -/* Copyright 2002, The libsigc++ Development Team +/* Copyright 2002 - 2016, The libsigc++ Development Team * Assigned to public domain. Use as you wish without restriction. */ #include "testutilities.h" -#include -#include #include #include -#include namespace { std::ostringstream result_stream; -class my_class: public sigc::trackable +class my_class : public sigc::trackable { public: - - my_class() - : i(0) - {} + my_class() : i(0) {} my_class(const my_class& src) = delete; my_class& operator=(const my_class& src) = delete; - my_class(my_class&& src) - : sigc::trackable(std::move(src)), - i(std::move(src.i)) + my_class(my_class&& src) noexcept : sigc::trackable(std::move(src)), i(std::move(src.i)) { src.i = 0; } - my_class& operator=(my_class&& src) + my_class& operator=(my_class&& src) noexcept { sigc::trackable::operator=(std::move(src)); i = std::move(src.i); - src.i = 0; + src.i = 0; // Make the moved-from object zeroed. Undefined behaviour would be acceptable too. return *this; } - void foo() - { - result_stream << i; - } + void foo() { result_stream << i; } int i; }; } // end anonymous namespace -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::slot sl; + sigc::slot sl; { my_class t; t.i = 10; - sl = sigc::mem_fun0(&t, &my_class::foo); + sl = sigc::mem_fun(t, &my_class::foo); sl(); util->check_result(result_stream, "10"); - //Create another trackable via a move: + // Create another trackable via a move: my_class t2(std::move(t)); t2.i = 15; result_stream.clear(); - sl = sigc::mem_fun0(&t2, &my_class::foo); + sl = sigc::mem_fun(t2, &my_class::foo); sl(); util->check_result(result_stream, "15"); diff --git a/tests/test_tuple_cdr.cc b/tests/test_tuple_cdr.cc new file mode 100644 index 00000000..da977626 --- /dev/null +++ b/tests/test_tuple_cdr.cc @@ -0,0 +1,92 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see +#include +#include +#include +#include + +void +test_tuple_type_cdr() +{ + using type_tuple_isd = std::tuple; + using type_tuple_sd = std::tuple; + using type_tuple_suffix = sigc::internal::tuple_type_cdr::type; + + static_assert( + std::tuple_size::value == 2, "unexpected tuple_cdr()ed tuple size."); + static_assert( + std::is_same::value, "unexpected tuple_cdr()ed tuple type"); +} + +void +test_tuple_cdr() +{ + auto t_larger = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_suffix = sigc::internal::tuple_cdr(t_larger); + assert(std::get<0>(t_suffix) == "hello"); + assert(std::get<1>(t_suffix) == "world"); + + using type_tuple_suffix = std::tuple; + + static_assert(std::tuple_size::value == 2, "unexpected cdr()ed tuple size."); + static_assert( + std::is_same::value, "unexpected cdr()ed tuple type"); +} + +void +test_tuple_cdr_stdref() +{ + std::string b = "yadda"; + std::string c = "yaddayadda"; + auto t_larger = std::make_tuple(1, std::ref(b), std::ref(c)); + + // std::cout << "debug: " << type(std::get<1>(t_larger)) << std::endl; + + auto t_suffix = sigc::internal::tuple_cdr(t_larger); + b = "hello"; + c = "world"; + // This works, but it's not what we are testing here: + // assert(std::get<1>(t_larger) == "hello"); + + assert(std::get<0>(t_suffix) == "hello"); + assert(std::get<1>(t_suffix) == "world"); +} + +constexpr void +test_tuple_cdr_constexpr() +{ + constexpr auto str_hello = "hello"; + constexpr auto str_world = "world"; + + constexpr auto t_larger = std::make_tuple(nullptr, str_hello, str_world); + constexpr auto t_suffix = sigc::internal::tuple_cdr(t_larger); + assert(std::get<0>(t_suffix) == str_hello); + assert(std::get<1>(t_suffix) == str_world); +} + +int +main() +{ + test_tuple_type_cdr(); + test_tuple_cdr(); + test_tuple_cdr_stdref(); + + test_tuple_cdr_constexpr(); + + return EXIT_SUCCESS; +} diff --git a/tests/test_tuple_end.cc b/tests/test_tuple_end.cc new file mode 100644 index 00000000..4b8de242 --- /dev/null +++ b/tests/test_tuple_end.cc @@ -0,0 +1,113 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see +#include +#include +#include +#include + +void +test_tuple_end() +{ + { + auto t_original = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_suffix = sigc::internal::tuple_end<3>(t_original); + + static_assert( + std::tuple_size::value == 3, "unexpected tuple_end()ed tuple size."); + + assert(std::get<0>(t_suffix) == nullptr); + assert(std::get<1>(t_suffix) == "hello"); + assert(std::get<2>(t_suffix) == "world"); + + static_assert(std::is_same::value, + "unexpected end()ed tuple type"); + } + + { + auto t_original = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_suffix = sigc::internal::tuple_end<2>(t_original); + + static_assert( + std::tuple_size::value == 2, "unexpected tuple_end()ed tuple size."); + + assert(std::get<0>(t_suffix) == "hello"); + assert(std::get<1>(t_suffix) == "world"); + + using type_tuple_suffix = std::tuple; + static_assert( + std::is_same::value, "unexpected end()ed tuple type"); + } + + { + auto t_original = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_suffix = sigc::internal::tuple_end<1>(t_original); + + static_assert( + std::tuple_size::value == 1, "unexpected tuple_end()ed tuple size."); + + assert(std::get<0>(t_suffix) == "world"); + + using type_tuple_suffix = std::tuple; + static_assert( + std::is_same::value, "unexpected end()ed tuple type"); + } +} + +void +test_tuple_end_stdref() +{ + std::string c = "yadda"; + std::string d = "yaddayadda"; + auto t_larger = std::make_tuple(1, 2, std::ref(c), std::ref(d)); + + auto t_suffix = sigc::internal::tuple_end<2>(t_larger); + c = "hello"; + d = "world"; + // This works, but it's not what we are testing here: + // assert(std::get<0>(t_larger) == "hello"); + + assert(std::get<0>(t_suffix) == "hello"); + assert(std::get<1>(t_suffix) == "world"); +} + +constexpr void +test_tuple_end_constexpr() +{ + constexpr auto str_hello = "hello"; + constexpr auto str_world = "world"; + + constexpr auto t_original = std::make_tuple(nullptr, str_hello, str_world); + constexpr auto t_suffix = sigc::internal::tuple_end<2>(t_original); + + static_assert( + std::tuple_size::value == 2, "unexpected tuple_end()ed tuple size."); + + assert(std::get<0>(t_suffix) == str_hello); + assert(std::get<1>(t_suffix) == str_world); +} + +int +main() +{ + test_tuple_end(); + test_tuple_end_stdref(); + + test_tuple_end_constexpr(); + + return EXIT_SUCCESS; +} diff --git a/tests/test_tuple_for_each.cc b/tests/test_tuple_for_each.cc new file mode 100644 index 00000000..003ecdc9 --- /dev/null +++ b/tests/test_tuple_for_each.cc @@ -0,0 +1,247 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see +#include +#include +#include +#include +#include + +template +class for_each_simple +{ +public: + static void visit(const T_element_from& from) + { + std::cout << "for_each_simple(): " << std::to_string(from) << std::endl; + } +}; + +void +test_tuple_for_each_same_types() +{ + { + auto t_original = std::make_tuple(1, 2, 3); + sigc::internal::tuple_for_each(t_original); + } + + { + auto t_original = std::make_tuple(1, static_cast(2.1f), 3); + sigc::internal::tuple_for_each(t_original); + } +} + +template +class for_each_simple_with_extras +{ +public: + static void visit(const T_element_from& from, int extra1, const std::string& extra2) + { + std::cout << "for_each_simple_with_extras(): from=" << std::to_string(from) + << ", extra1: " << extra1 << ", extra2: " << extra2 << std::endl; + } +}; + +void +test_tuple_for_each_same_types_with_extras() +{ + { + auto t_original = std::make_tuple(1, static_cast(2.1f), 3); + sigc::internal::tuple_for_each(t_original, 89, "eightynine"); + } +} + +template +class for_each_simple_with_nonconst_extras +{ +public: + static void visit(const T_element_from& from, int& extra) { extra += (int)from; } +}; + +void +test_tuple_for_each_same_types_with_nonconst_extras() +{ + { + auto t_original = std::make_tuple(1, static_cast(2.1f), 3); + int extra = 0; + + sigc::internal::tuple_for_each(t_original, extra); + // std::cout << "extra: " << extra << std::endl; + assert(extra == 6); + } +} + +// The general template declaration. +// We then provide specializations for each type, +// so we can test having a different return value for each T_element_from type. +template +class visitor_with_specializations; + +// An int will be converted to a std::string: +template<> +class visitor_with_specializations +{ +public: + static void visit(const int& from) + { + std::cout << "visitor_with_specializations::visit(): " << std::to_string(from) << std::endl; + } +}; + +// A double will be converted to a char: +template<> +class visitor_with_specializations +{ +public: + static void visit(const double& from) + { + std::cout << "visitor_with_specializations::visit(): " << std::to_string(from)[0] << std::endl; + } +}; + +// A std::string will be converted to an int: +template<> +class visitor_with_specializations +{ +public: + static void visit(const std::string& from) + { + std::cout << "visitor_with_specializations::visit(): " << std::stoi(from) << std::endl; + } +}; + +// A const char* will be converted to an int: +template<> +class visitor_with_specializations +{ +public: + static void visit(const char* from) + { + std::cout << "visitor_with_specializations::visit(): " << std::stoi(from) << std::endl; + } +}; + +void +test_tuple_for_each_multiple_types() +{ + auto t_original = std::make_tuple(1, static_cast(2.1f), std::string("3")); + sigc::internal::tuple_for_each(t_original); +} + +template +class for_each_nonconst +{ +public: + static void visit(T_element_from& from) + { + from *= 2; + // Or, for instance, call a non-const method on from. + } +}; + +void +test_tuple_for_each_nonconst() +{ + auto t = std::make_tuple(1, 2, 3); + sigc::internal::tuple_for_each(t); + std::cout << std::get<0>(t) << std::endl; + assert(std::get<0>(t) == 2); + assert(std::get<1>(t) == 4); + assert(std::get<2>(t) == 6); +} + +void +test_tuple_for_each_stdref() +{ + { + int a = 1; + int b = 2; + int c = 3; + auto t_original = std::make_tuple(std::ref(a), std::ref(b), std::ref(c)); + sigc::internal::tuple_for_each(t_original); + } + + { + int a = 1; + int b = 2; + int c = 3; + auto t_original = std::make_tuple(std::ref(a), std::ref(b), std::ref(c)); + sigc::internal::tuple_for_each(t_original); + assert(a == 2); + assert(b == 4); + assert(c == 6); + } +} + +static std::string correct_sequence_output; + +template +class for_each_correct_sequence +{ +public: + static void visit(const T_element_from& from) + { + // std::cout << "from: " << from << std::endl; + correct_sequence_output += std::to_string(from); + } +}; + +void +test_tuple_for_each_correct_sequence() +{ + correct_sequence_output.clear(); + auto t = std::make_tuple(1, 2, 3); + sigc::internal::tuple_for_each(t); + // std::cout << "correct_sequence_output: " << correct_sequence_output << std::endl; + assert(correct_sequence_output == "123"); +} + +void +test_tuple_for_each_empty_tuple() +{ + auto t = std::tuple<>(); + sigc::internal::tuple_for_each(t); +} + +constexpr void +test_tuple_for_each_constexpr() +{ + constexpr auto t_original = std::make_tuple(1, static_cast(2.1f), "3"); + sigc::internal::tuple_for_each(t_original); +} + +int +main() +{ + test_tuple_for_each_same_types(); + test_tuple_for_each_same_types_with_extras(); + test_tuple_for_each_same_types_with_nonconst_extras(); + + test_tuple_for_each_multiple_types(); + + test_tuple_for_each_nonconst(); + + test_tuple_for_each_stdref(); + + test_tuple_for_each_correct_sequence(); + + test_tuple_for_each_empty_tuple(); + + test_tuple_for_each_constexpr(); + + return EXIT_SUCCESS; +} diff --git a/tests/test_tuple_start.cc b/tests/test_tuple_start.cc new file mode 100644 index 00000000..0e73fcd1 --- /dev/null +++ b/tests/test_tuple_start.cc @@ -0,0 +1,143 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see +#include +#include +#include +#include + +void +test_tuple_type_start() +{ + { + using type_tuple = std::tuple; + using type_tuple_start = sigc::internal::tuple_type_start::type; + using type_tuple_expected = std::tuple; + + static_assert(std::is_same::value, + "unexpected type_tuple_start type"); + } + + { + using type_tuple = std::tuple; + using type_tuple_start = sigc::internal::tuple_type_start::type; + using type_tuple_expected = std::tuple; + + static_assert(std::is_same::value, + "unexpected type_tuple_start type"); + } + + { + using type_tuple = std::tuple; + using type_tuple_start = sigc::internal::tuple_type_start::type; + using type_tuple_expected = std::tuple; + + static_assert(std::is_same::value, + "unexpected type_tuple_start type"); + } +} + +void +test_tuple_start() +{ + { + auto t_original = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_prefix = sigc::internal::tuple_start<3>(t_original); + + static_assert( + std::tuple_size::value == 3, "unexpected tuple_start()ed tuple size."); + + assert(std::get<0>(t_prefix) == nullptr); + assert(std::get<1>(t_prefix) == "hello"); + assert(std::get<2>(t_prefix) == "world"); + + static_assert(std::is_same::value, + "unexpected start()ed tuple type"); + } + + { + auto t_original = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_prefix = sigc::internal::tuple_start<2>(t_original); + + static_assert( + std::tuple_size::value == 2, "unexpected tuple_start()ed tuple size."); + + assert(std::get<0>(t_prefix) == nullptr); + assert(std::get<1>(t_prefix) == "hello"); + + using type_tuple_prefix = std::tuple; + static_assert(std::is_same::value, + "unexpected start()ed tuple type"); + } + + { + auto t_original = std::make_tuple(nullptr, std::string("hello"), std::string("world")); + auto t_prefix = sigc::internal::tuple_start<1>(t_original); + + static_assert( + std::tuple_size::value == 1, "unexpected tuple_start()ed tuple size."); + + assert(std::get<0>(t_prefix) == nullptr); + + using type_tuple_prefix = std::tuple; + static_assert(std::is_same::value, + "unexpected start()ed tuple type"); + } +} + +void +test_tuple_start_stdref() +{ + std::string a = "yadda"; + std::string b = "yaddayadda"; + auto t_larger = std::make_tuple(std::ref(a), std::ref(b), 1); + + auto t_prefix = sigc::internal::tuple_start<2>(t_larger); + a = "hello"; + b = "world"; + // This works, but it's not what we are testing here: + // assert(std::get<0>(t_larger) == "hello"); + + assert(std::get<0>(t_prefix) == "hello"); + assert(std::get<1>(t_prefix) == "world"); +} + +constexpr void +test_tuple_start_constexpr() +{ + constexpr auto str_hello = "hello"; + constexpr auto str_world = "hello"; + + constexpr auto t_original = std::make_tuple(nullptr, str_hello, str_world); + constexpr auto t_prefix = sigc::internal::tuple_start<2>(t_original); + + static_assert( + std::tuple_size::value == 2, "unexpected tuple_start()ed tuple size."); + + assert(std::get<0>(t_prefix) == nullptr); + assert(std::get<1>(t_prefix) == str_hello); +} + +int +main() +{ + test_tuple_type_start(); + test_tuple_start(); + test_tuple_start_stdref(); + + test_tuple_start_constexpr(); +} diff --git a/tests/test_tuple_transform_each.cc b/tests/test_tuple_transform_each.cc new file mode 100644 index 00000000..c5a4b87d --- /dev/null +++ b/tests/test_tuple_transform_each.cc @@ -0,0 +1,311 @@ +/* Copyright (C) 2016 Murray Cumming + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see +#include +#include +#include +#include +#include + +template +class transform_to_string +{ +public: + static decltype(auto) transform(T_element_from& from) { return std::to_string(from); } +}; + +// In these tests, t_expected has elements all of the same type. +void +test_tuple_transform_each_same_types() +{ + { + auto t_original = std::make_tuple(1, 2, 3); + auto t_transformed = sigc::internal::tuple_transform_each(t_original); + auto t_expected = std::make_tuple(std::string("1"), std::string("2"), std::string("3")); + + static_assert(std::tuple_size::value == 3, + "unexpected tuple_transform_each()ed tuple size."); + + assert(std::get<0>(t_transformed) == "1"); + assert(std::get<1>(t_transformed) == "2"); + assert(std::get<2>(t_transformed) == "3"); + + static_assert(std::is_same::value, + "unexpected transform_each()ed tuple type"); + } + + { + auto t_original = std::make_tuple(1, static_cast(2.1f), 3); + auto t_transformed = sigc::internal::tuple_transform_each(t_original); + auto t_expected = std::make_tuple(std::string("1"), std::string("2"), std::string("3")); + + static_assert(std::tuple_size::value == 3, + "unexpected tuple_transform_each()ed tuple size."); + + assert(std::get<0>(t_transformed) == "1"); + assert(std::get<1>(t_transformed).substr(0, 3) == "2.1"); + assert(std::get<2>(t_transformed) == "3"); + + static_assert(std::is_same::value, + "unexpected transform_each()ed tuple type"); + } +} + +// The general template declaration. +// We then provide specializations for each type, +// so we can test having a different return value for each T_element_from type. +template +class transform_to_something; + +// An int will be converted to a std::string: +template<> +class transform_to_something +{ +public: + static std::string transform(int& from) { return std::to_string(from); } +}; + +// A double will be converted to a char: +template<> +class transform_to_something +{ +public: + static char transform(double& from) { return std::to_string(from)[0]; } +}; + +// A std::string will be converted to an int: +template<> +class transform_to_something +{ +public: + static int transform(std::string& from) { return std::stoi(from); } +}; + +// In these tests, t_expected has elements of different types. +void +test_tuple_transform_each_multiple_types() +{ + auto t_original = std::make_tuple(1, static_cast(2.1f), std::string("3")); + auto t_transformed = sigc::internal::tuple_transform_each(t_original); + auto t_expected = std::make_tuple(std::string("1"), '2', 3); + + static_assert(std::tuple_size::value == 3, + "unexpected tuple_transform_each()ed tuple size."); + + assert(std::get<0>(t_transformed) == "1"); + assert(std::get<1>(t_transformed) == '2'); + assert(std::get<2>(t_transformed) == 3); + + static_assert(std::is_same::value, + "unexpected transform_each()ed tuple type"); +} + +template +class transform_each_nonconst +{ +public: + static int transform(T_element_from& from) + { + from *= 2; + // Or, for instance, call a non-const method on from. + + return from * 10; + } +}; + +void +test_tuple_transform_each_nonconst() +{ + auto t = std::make_tuple(1, 2, 3); + auto t_transformed = sigc::internal::tuple_transform_each(t); + + // Check that t was changed (from * 2): + assert(std::get<0>(t) == 2); + assert(std::get<1>(t) == 4); + assert(std::get<2>(t) == 6); + + // Check that t_transformed has the expected values ( from * 2 * 10): + assert(std::get<0>(t_transformed) == 20); + assert(std::get<1>(t_transformed) == 40); + assert(std::get<2>(t_transformed) == 60); +} + +void +test_tuple_transform_each_stdref() +{ + int a = 1; + int b = 2; + int c = 3; + auto t_original = std::make_tuple(std::ref(a), std::ref(b), std::ref(c)); + auto t_transformed = sigc::internal::tuple_transform_each(t_original); + auto t_expected = std::make_tuple(std::string("1"), std::string("2"), std::string("3")); + + static_assert(std::tuple_size::value == 3, + "unexpected tuple_transform_each()ed tuple size."); + + assert(std::get<0>(t_transformed) == "1"); + assert(std::get<1>(t_transformed) == "2"); + assert(std::get<2>(t_transformed) == "3"); + + static_assert(std::is_same::value, + "unexpected transform_each()ed tuple type"); +} + +// This can only be used via std::ref(), for instance. +// Any attempt to copy or move it, should cause a compiler error. +class NonCopyable +{ +public: + explicit NonCopyable(int val) : m_val(val) {} + + int get_val() const { return m_val; } + + NonCopyable(const NonCopyable& src) = delete; + NonCopyable& operator=(const NonCopyable& src) = delete; + + NonCopyable(NonCopyable&& src) = delete; + NonCopyable& operator=(NonCopyable&& src) = delete; + +private: + int m_val; +}; + +template +class transform_noncopyable_to_string +{ +public: + static decltype(auto) transform(T_element_from&& from) { return std::to_string(from.get_val()); } +}; + +void +test_tuple_transform_each_stdref_non_copyable() +{ + NonCopyable a(1); + NonCopyable b(2); + NonCopyable c(3); + auto t_original = std::make_tuple(std::ref(a), std::ref(b), std::ref(c)); + auto t_transformed = + sigc::internal::tuple_transform_each(t_original); + auto t_expected = std::make_tuple(std::string("1"), std::string("2"), std::string("3")); + + static_assert(std::tuple_size::value == 3, + "unexpected tuple_transform_each()ed tuple size."); + + assert(std::get<0>(t_transformed) == "1"); + assert(std::get<1>(t_transformed) == "2"); + assert(std::get<2>(t_transformed) == "3"); + + static_assert(std::is_same::value, + "unexpected transform_each()ed tuple type"); +} + +static std::string correct_sequence_output; + +template +class transform_each_correct_sequence +{ +public: + static decltype(auto) transform(int from) + { + correct_sequence_output += std::to_string(from); + return std::to_string(from); + } +}; + +void +test_tuple_transform_each_correct_sequence() +{ + correct_sequence_output.clear(); + auto t = std::make_tuple(1, 2, 3); + sigc::internal::tuple_transform_each(t); + // std::cout << "correct_sequence_output: " << correct_sequence_output << std::endl; + assert(correct_sequence_output == "123"); +} + +void +test_tuple_transform_each_empty_tuple() +{ + auto t = std::tuple<>(); + sigc::internal::tuple_transform_each(t); +} + +// The general template declaration. +// We then provide specializations for each type, +// so we can test having a different return value for each T_element_from type. +template +class transform_as_constexpr_to_something; + +// An int will be converted to a char: +template<> +class transform_as_constexpr_to_something +{ +public: + constexpr static char transform(int from) { return 'a' + static_cast(from); } +}; + +// A double will be converted to an int: +template<> +class transform_as_constexpr_to_something +{ +public: + constexpr static int transform(double from) { return (int)from; } +}; + +/* TODO: See the comment in main(). +constexpr +void +test_tuple_transform_each_constexpr() { + constexpr auto t_original = std::make_tuple(1, static_cast(2.1f)); + constexpr auto t_transformed = + sigc::internal::tuple_transform_each(t_original); + constexpr auto t_expected = std::make_tuple('b', 2); + + static_assert(std::tuple_size::value == 2, + "unexpected tuple_transform_each()ed tuple size."); + + assert(std::get<0>(t_transformed) == 'b'); + assert(std::get<1>(t_transformed) == 2); + + static_assert( + std::is_same::value, + "unexpected transform_each()ed tuple type"); +} +*/ + +int +main() +{ + test_tuple_transform_each_same_types(); + test_tuple_transform_each_multiple_types(); + + test_tuple_transform_each_nonconst(); + + test_tuple_transform_each_stdref(); + test_tuple_transform_each_stdref_non_copyable(); + + test_tuple_transform_each_correct_sequence(); + + test_tuple_transform_each_empty_tuple(); + + // g++ 5.2.1 gives this error: + // error: accessing uninitialized member ‘std::tuple::’ + // though it works with clang++. + // TODO: Try it with a newer g++. + // test_tuple_transform_each_constexpr(); + + return EXIT_SUCCESS; +} diff --git a/tests/test_visit_each.cc b/tests/test_visit_each.cc index a63fa435..adb59da8 100644 --- a/tests/test_visit_each.cc +++ b/tests/test_visit_each.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2014 The libsigc++ Development Team +/* Copyright (C) 2014 - 2016, The libsigc++ Development Team * * This file is part of libsigc++. * @@ -17,11 +17,9 @@ */ #include "testutilities.h" -#include #include -#include -#include #include +#include // SIGCTEST_CASE 1 Assume that class sigc::visitor has not been implemented. // Don't test with MyClass2, which is expected to fail in this case. @@ -44,8 +42,9 @@ class NsExtClass { }; -template -void visit_each(T_action&, const T_functor&) +template +void +visit_each(T_action&, const T_functor&) { result_stream << "ns_ext::visit_each() "; } @@ -57,25 +56,23 @@ namespace class MyClass1 : public sigc::trackable { public: - MyClass1(const std::string& str) : s(str) {} + explicit MyClass1(const std::string& str) : s(str) {} + + void execute(int i) { result_stream << s << i; } - void execute(int i) - { - result_stream << s << i; - } private: std::string s; }; -class MyClass2 : public ns_ext::NsExtClass, public sigc::trackable +class MyClass2 +: public ns_ext::NsExtClass +, public sigc::trackable { public: - MyClass2(const std::string& str) : s(str) {} + explicit MyClass2(const std::string& str) : s(str) {} + + void execute(int i) { result_stream << s << i; } - void execute(int i) - { - result_stream << s << i; - } private: std::string s; }; @@ -85,55 +82,46 @@ class MyClass2 : public ns_ext::NsExtClass, public sigc::trackable namespace ns1 { // User-defined adaptor, as decribed in adaptor_trait.h. -template +template struct MyAdaptor1 : public sigc::adapts { - template - struct deduce_result_type - { typedef sigc::deduce_result_t type; }; - typedef typename sigc::functor_trait::result_type result_type; - - result_type - operator()() const + decltype(auto) operator()() const { result_stream << "MyAdaptor1()() "; return this->functor_(); } - template - typename deduce_result_type::type - operator()(T_arg1 _A_arg1) const + template + decltype(auto) operator()(T_arg1 arg1) const { - result_stream << "MyAdaptor1()(_A_arg1) "; - return this->functor_(_A_arg1); + result_stream << "MyAdaptor1()(arg1) "; + return this->functor_(arg1); } - template - typename deduce_result_type::type - operator()(T_arg1 _A_arg1, T_arg2 _A_arg2) const + template + decltype(auto) operator()(T_arg1 arg1, T_arg2 arg2) const { - result_stream << "MyAdaptor1()(_A_arg1, _A_arg2) "; - return this->functor_(_A_arg1, _A_arg2); + result_stream << "MyAdaptor1()(arg1, arg2) "; + return this->functor_(arg1, arg2); } // Constructs a MyAdaptor1 object that wraps the passed functor. // Initializes adapts::functor_, which is invoked from operator()(). - explicit MyAdaptor1(const T_functor& _A_functor) - : sigc::adapts(_A_functor) {} + explicit MyAdaptor1(const T_functor& functor) : sigc::adapts(functor) {} }; -template -void visit_each(const T_action& _A_action, - const MyAdaptor1& _A_target) +template +void +visit_each(const T_action& action, const MyAdaptor1& target) { - visit_each(_A_action, _A_target.functor_); + visit_each(action, target.functor_); } -template +template inline MyAdaptor1 -my_adaptor1(const T_functor& _A_func) +my_adaptor1(const T_functor& func) { - return MyAdaptor1(_A_func); + return MyAdaptor1(func); } } // end namespace ns1 @@ -142,32 +130,31 @@ my_adaptor1(const T_functor& _A_func) // Specialization of sigc::visitor for MyAdaptor1. namespace sigc { -template -struct visitor > +template +struct visitor> { - template - static void do_visit_each(const T_action& _A_action, - const ns1::MyAdaptor1& _A_target) + template + static void do_visit_each(const T_action& action, const ns1::MyAdaptor1& target) { - sigc::visit_each(_A_action, _A_target.functor_); + sigc::visit_each(action, target.functor_); } }; } // end namespace sigc #endif // SIGCTEST_CASE >= 3 - -int main(int argc, char* argv[]) +int +main(int argc, char* argv[]) { auto util = TestUtilities::get_instance(); if (!util->check_command_args(argc, argv)) return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; - sigc::slot sl1; + sigc::slot sl1; { MyClass1 my_class1("x="); - sl1 = sigc::mem_fun(&my_class1, &MyClass1::execute); + sl1 = sigc::mem_fun(my_class1, &MyClass1::execute); sl1(-2); util->check_result(result_stream, "x=-2"); @@ -179,7 +166,7 @@ int main(int argc, char* argv[]) #if SIGCTEST_CASE >= 2 { MyClass2 my_class2("y="); - sl1 = sigc::mem_fun(&my_class2, &MyClass2::execute); + sl1 = sigc::mem_fun(my_class2, &MyClass2::execute); sl1(2); util->check_result(result_stream, "y=2"); @@ -191,9 +178,9 @@ int main(int argc, char* argv[]) { MyClass1 my_class3("a="); - sl1 = ns1::my_adaptor1(sigc::mem_fun(&my_class3, &MyClass1::execute)); + sl1 = ns1::my_adaptor1(sigc::mem_fun(my_class3, &MyClass1::execute)); sl1(42); - util->check_result(result_stream, "MyAdaptor1()(_A_arg1) a=42"); + util->check_result(result_stream, "MyAdaptor1()(arg1) a=42"); } // auto-disconnect sl1 diff --git a/tests/test_visit_each_trackable.cc b/tests/test_visit_each_trackable.cc new file mode 100644 index 00000000..720fcfbd --- /dev/null +++ b/tests/test_visit_each_trackable.cc @@ -0,0 +1,101 @@ +/* Copyright 2002 - 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include "testutilities.h" +#include +#include //For std::ref(). +#include +#include +#include +#include +#include + +namespace +{ + +TestUtilities* util = nullptr; +std::ostringstream result_stream; + +struct A : public sigc::trackable +{ + A() {} +}; + +template::value> +struct with_trackable; + +template +struct with_trackable +{ + static void perform(const T_type&) { result_stream << "other "; } +}; + +template +struct with_trackable +{ + static void perform(const T_type&) { result_stream << "trackable "; } + + static void perform(T_type*) { result_stream << "trackable* "; } + + static void perform(const T_type*) { result_stream << "const trackable* "; } +}; + +struct print +{ + void operator()(int i) const { result_stream << "int: " << i << " "; } + + template + void operator()(const T& t) const + { + with_trackable::perform(t); + } +}; + +void +foo(int, int, int) +{ +} + +void +bar(int) +{ +} + +} // end anonymous namespace + +void +test_hit_all_targets() +{ + int i = 1; + A a; + result_stream << "hit all targets: "; + sigc::visit_each( + print(), sigc::compose(sigc::bind(sigc::ptr_fun(&foo), std::ref(a), i), sigc::ptr_fun(&bar))); + util->check_result(result_stream, "hit all targets: other trackable int: 1 other "); +} + +void +test_hit_all_trackable() +{ + int i = 3; + A a; + result_stream << "hit all trackable: "; + sigc::visit_each_trackable( + print(), sigc::compose(sigc::bind(sigc::ptr_fun(&foo), std::ref(a), i), sigc::ptr_fun(&bar))); + util->check_result(result_stream, "hit all trackable: trackable "); +} + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_hit_all_targets(); + test_hit_all_trackable(); + + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/test_weak_raw_ptr.cc b/tests/test_weak_raw_ptr.cc new file mode 100644 index 00000000..c6ffc38d --- /dev/null +++ b/tests/test_weak_raw_ptr.cc @@ -0,0 +1,72 @@ +/* Copyright 2016, The libsigc++ Development Team + * Assigned to public domain. Use as you wish without restriction. + */ + +#include "testutilities.h" +#include +#include + +namespace +{ + +TestUtilities* util = nullptr; +std::ostringstream result_stream; + +class A : public sigc::trackable +{ +public: + void something() { result_stream << "method called"; } +}; + +} // end anonymous namespace + +void +test_weak_ptr_becomes_null() +{ + const auto a = new A(); + sigc::internal::weak_raw_ptr raw_ptr(a); + assert(raw_ptr); + + // Call something on A, via the weak_raw_ptr<>, + // just to make sure that it doesn't get optimised away: + raw_ptr->something(); + util->check_result(result_stream, "method called"); + + delete a; + + // Deleting the A should have made the weak_raw_ptr become invalid. + assert(!raw_ptr); +} + +void +test_weak_ptr_disconnects_self() +{ + const auto a = new A(); + { + sigc::internal::weak_raw_ptr raw_ptr(a); + + // Call something on A, via the weak_raw_ptr<>, + // just to make sure that it doesn't get optimised away: + raw_ptr->something(); + util->check_result(result_stream, "method called"); + } + + // If the weak_raw_ptr has not asked A to stop notifying it, + // then we would expect some undefined behaviour here, + // when a tries to notify the now-destroyed weak_raw_ptr. + delete a; +} + +int +main(int argc, char* argv[]) +{ + util = TestUtilities::get_instance(); + + if (!util->check_command_args(argc, argv)) + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; + + test_weak_ptr_becomes_null(); + test_weak_ptr_disconnects_self(); + + return util->get_result_and_delete_instance() ? EXIT_SUCCESS : EXIT_FAILURE; +} diff --git a/tests/testutilities.cc b/tests/testutilities.cc index 4d8de22c..ae9e11c0 100644 --- a/tests/testutilities.cc +++ b/tests/testutilities.cc @@ -1,4 +1,4 @@ -/* Copyright (C) 2012 The libsigc++ Development Team +/* Copyright (C) 2012 - 2016, The libsigc++ Development Team * * This file is part of libsigc++. * @@ -23,13 +23,11 @@ TestUtilities* TestUtilities::instance_ = nullptr; -TestUtilities::TestUtilities() -: verbose_(false), result_ok_(true), test_number_(0) -{ -} +TestUtilities::TestUtilities() : verbose_(false), result_ok_(true), test_number_(0) {} -//static -TestUtilities* TestUtilities::get_instance() +// static +TestUtilities* +TestUtilities::get_instance() { if (!instance_) instance_ = new TestUtilities; @@ -37,7 +35,8 @@ TestUtilities* TestUtilities::get_instance() return instance_; } -bool TestUtilities::check_command_args(int argc, char* argv[]) +bool +TestUtilities::check_command_args(int argc, char* argv[]) { bool go_on = true; // Whether the caller shall continue program execution. bool print_help = false; @@ -65,8 +64,8 @@ bool TestUtilities::check_command_args(int argc, char* argv[]) return go_on; } -void TestUtilities::check_result(std::ostringstream& result_stream, - const std::string& expected_result) +void +TestUtilities::check_result(std::ostringstream& result_stream, const std::string& expected_result) { if (verbose_) std::cout << result_stream.str() << std::endl; @@ -82,8 +81,9 @@ void TestUtilities::check_result(std::ostringstream& result_stream, result_stream.str(""); } -//static -bool TestUtilities::get_result_and_delete_instance() +// static +bool +TestUtilities::get_result_and_delete_instance() { const bool result = instance_ ? instance_->result_ok_ : true; delete instance_; diff --git a/tests/testutilities.h b/tests/testutilities.h index f06d6d90..772689dc 100644 --- a/tests/testutilities.h +++ b/tests/testutilities.h @@ -24,7 +24,6 @@ class TestUtilities { public: - // Non-copyable: TestUtilities(const TestUtilities&) = delete; TestUtilities& operator=(const TestUtilities&) = delete; @@ -44,8 +43,6 @@ class TestUtilities static bool get_result_and_delete_instance(); private: - - TestUtilities(); static TestUtilities* instance_; diff --git a/tools/handle-built-files.py b/tools/handle-built-files.py new file mode 100644 index 00000000..fc1f9b6f --- /dev/null +++ b/tools/handle-built-files.py @@ -0,0 +1,46 @@ +#!/usr/bin/env python3 + +# External command, intended to be called with run_command(), custom_target(), +# meson.add_install_script() and meson.add_dist_script(). + +# argv[1] argv[2:] +# handle-built-files.py ... + +import os +import sys +import shutil +import subprocess +from pathlib import Path + +subcommand = sys.argv[1] + +# Invoked from meson.add_dist_script(). +def dist_built_files(is_msvc_files=False): + # argv[2] argv[3] argv[4:] + # ... + + # is an absolute path in the build directory or source directory. + # is a distribution directory, relative to MESON_PROJECT_DIST_ROOT. + + # MESON_PROJECT_DIST_ROOT is set only if meson.version() >= 0.58.0. + project_dist_root = os.getenv('MESON_PROJECT_DIST_ROOT', os.getenv('MESON_DIST_ROOT')) + built_h_cc_dir = sys.argv[2] + dist_dir_root = os.path.join(project_dist_root, sys.argv[3]) + dist_dir = dist_dir_root + + # Distribute .h and .cc files built from .m4 files, or generated MSVC files. + for file in sys.argv[4:]: + if not is_msvc_files: + dist_dir = os.path.join(dist_dir_root, os.path.dirname(file)) + + # Create the distribution directory, if it does not exist. + os.makedirs(dist_dir, exist_ok=True) + + shutil.copy(os.path.join(built_h_cc_dir, file), dist_dir) + return 0 + +# ----- Main ----- +if subcommand == 'dist_gen_msvc_files': + sys.exit(dist_built_files(True)) +print(sys.argv[0], ': illegal subcommand,', subcommand) +sys.exit(1) diff --git a/tools/tutorial-custom-cmd.py b/tools/tutorial-custom-cmd.py new file mode 100755 index 00000000..280d2559 --- /dev/null +++ b/tools/tutorial-custom-cmd.py @@ -0,0 +1,216 @@ +#!/usr/bin/env python3 + +# External command, intended to be called with custom_target() in meson.build + +# argv[1] argv[2:] +# tutorial-custom-cmd.py ... + +import os +import sys +import subprocess +import shutil + +subcommand = sys.argv[1] + +def html(): + # argv[2] argv[3] + # + + input_xml_file = sys.argv[2] + output_html_dir = sys.argv[3] + + # Set the use.id.as.filename param so that we don't use the chapter / section + # number as the filename, otherwise the url will change every time anything is + # re-ordered or inserted in the documentation. + # For a list of available parameters, see http://docbook.sourceforge.net/release/xsl/current/doc/html/ + xslt_params = [ + '--param', 'toc.section.depth', '1', + '--stringparam', 'chunker.output.indent', 'yes', + '--stringparam', 'chunker.output.encoding', 'UTF-8', + '--stringparam', 'toc.list.type', 'ul', + '--param', 'use.id.as.filename', '1', + ] + + # The recommended stylesheet for DocBook V5.0 is .../xsl-ns/... + # It's not used here because the docbook-xsl-ns package is not available + # when building with gnome-build-meta. + xslt_stylesheet = 'http://docbook.sourceforge.net/release/xsl/current/html/chunk.xsl' + + # Remove old files and create the destination directory. + shutil.rmtree(output_html_dir, ignore_errors=True) + os.makedirs(output_html_dir, exist_ok=True) + + cmd = [ + 'xsltproc', + ] + xslt_params + [ + '-o', output_html_dir + '/', + '--xinclude', + xslt_stylesheet, + input_xml_file, + ] + result = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, + universal_newlines=True) + # xsltproc prints the names of all written files. Don't print those lines. + for line in result.stdout.splitlines(): + if not line.startswith('Writing '): + print(line) + + return result.returncode + +def xmllint(): + from pathlib import Path + + # argv[2] argv[3] argv[4] + # + + validate = sys.argv[2] + input_xml_file = sys.argv[3] + stamp_file_path = sys.argv[4] + + relax_ng_schema = 'http://docbook.org/xml/5.0/rng/docbook.rng' + # schematron_schema = 'http://docbook.org/xml/5.0/sch/docbook.sch' + + # Validation against the Schematron schema does not work on Ubuntu 21.04: + # file:///usr/share/xml/docbook/schema/schematron/5.0/docbook.sch:6: element rule: + # Schemas parser error : Failed to compile context expression db:firstterm[@linkend] + # ..... + # Schematron schema http://docbook.org/xml/5.0/sch/docbook.sch failed to compile + + cmd = [ + 'xmllint', + '--noout', + '--noent', + '--xinclude', + ] + if validate == 'true': + cmd += [ + '--relaxng', relax_ng_schema, + #'--schematron', schematron_schema, + ] + cmd += [input_xml_file] + result = subprocess.run(cmd) + if result.returncode: + return result.returncode + + Path(stamp_file_path).touch(exist_ok=True) + return 0 + +# dblatex and xsltproc+fop generate a PDF file. +# docbook2pdf can generate PDF files from DocBook4 files, but not from DocBook5 files. +# xsltproc+xmlroff (version 0.6.3) does not seem to work acceptably. +def dblatex(): + # argv[2] argv[3] + # + # Create a PDF file, using dblatex. + + input_xml_file = sys.argv[2] + output_pdf_file = sys.argv[3] + + # For a list of available parameters, see http://dblatex.sourceforge.net/doc/manual/ + dblatex_params = [ + '-P', 'toc.section.depth=1', + '-P', 'paper.type=a4paper', + '-P', 'doc.collab.show=1', + '-P', 'latex.output.revhistory=0', + '-P', 'latex.engine.options="-halt-on-error"', + ] + + cmd = [ + 'dblatex', + ] + dblatex_params + [ + '-o', output_pdf_file, + '--pdf', + input_xml_file, + ] + return subprocess.run(cmd).returncode + +def fop(): + # argv[2] argv[3] + # + # Create a PDF file, using fop. + + input_xml_file = sys.argv[2] + output_pdf_file = sys.argv[3] + + fo_file = os.path.splitext(output_pdf_file)[0] + '.fo' + + # For a list of available parameters, see http://docbook.sourceforge.net/release/xsl/current/doc/fo/ + # For a list of available paper types, see the description of the page.width.portrait parameter. + xslt_params = [ + '--param', 'toc.section.depth', '1', + '--stringparam', 'fop1.extensions', '1', + '--stringparam', 'page.orientation', 'portrait', + '--stringparam', 'paper.type', 'A4', + ] + + xslt_stylesheet = 'http://docbook.sourceforge.net/release/xsl/current/fo/docbook.xsl' + + # Generate a .fo (formatting object) file. + # fop can take an xslt stylesheet parameter, but it can only read local files. + # xsltproc is necessary if you want to read the stylesheet from the internet. + cmd = [ + 'xsltproc', + ] + xslt_params + [ + '-o', fo_file, + '--xinclude', + xslt_stylesheet, + input_xml_file, + ] + result = subprocess.run(cmd) + if result.returncode: + return result.returncode + + cmd = [ + 'fop', + '-fo', fo_file, + '-pdf', output_pdf_file, + ] + return subprocess.run(cmd).returncode + +# Invoked from meson.add_dist_script(). +def dist_doc(): + # argv[2] argv[3] argv[4] argv[5] + # + + # is a distribution directory, relative to MESON_PROJECT_DIST_ROOT. + # is a relative or absolute path in the build directory. + # is a relative or absolute path in the source directory. + # is a relative or absolute path in the build directory. + + # MESON_PROJECT_DIST_ROOT is set only if meson.version() >= 0.58.0. + project_dist_root = os.getenv('MESON_PROJECT_DIST_ROOT', os.getenv('MESON_DIST_ROOT')) + doc_dist_dir = os.path.join(project_dist_root, sys.argv[2]) + doc_build_dir = sys.argv[3] + xml_file = sys.argv[4] + pdf_file = sys.argv[5] + + # Create the distribution directory, if it does not exist. + os.makedirs(doc_dist_dir, exist_ok=True) + + # Distribute built html files. + shutil.copytree(os.path.join(doc_build_dir, 'html'), + os.path.join(doc_dist_dir, 'html'), + copy_function=shutil.copy) + + # If there is an updated PDF file, distribute it. + if os.path.isfile(pdf_file) and \ + os.stat(pdf_file).st_mtime > os.stat(xml_file).st_mtime: + shutil.copy(pdf_file, doc_dist_dir) + else: + print('--- Info: No updated PDF file found.') + + return 0 + +# ----- Main ----- +if subcommand == 'html': + sys.exit(html()) +if subcommand == 'xmllint': + sys.exit(xmllint()) +if subcommand == 'dblatex': + sys.exit(dblatex()) +if subcommand == 'fop': + sys.exit(fop()) +if subcommand == 'dist_doc': + sys.exit(dist_doc()) +print(sys.argv[0], ': illegal subcommand,', subcommand) +sys.exit(1) diff --git a/untracked/README b/untracked/README new file mode 100644 index 00000000..dfefb62b --- /dev/null +++ b/untracked/README @@ -0,0 +1,36 @@ +untracked/README + +This directory contains files not tracked by a source code control program, +such as git. (This README file is the exception.) + +The files can have one of two origins. + +1. Copied by the mm-common-get command. +2. Generated when libsigc++ is built. + +Files of type 2 exist here only if libsigc++ is built with maintainer-mode=false, +or the directory comes from a tarball. +Files of both types exist here only if libsigc++ is built with Meson, +or the tarball is created with Meson. + +1. Files copied by mm-common-get +-------------------------------- +untracked/docs/docs/doc_install.py or doc-install.pl + doc_postprocess.py or doc-postprocess.pl + doxygen-extra.css + tagfile-to-devhelp2.xsl +untracked/build_scripts/dist-build-scripts.py + dist-changelog.py + doc-reference.py + +mm-common-get may copy more files, but they are not used by libsigc++. + +2. Generated files +------------------ +untracked/docs/docs/reference/libsigc++-3.0.devhelp2 + libsigc++-3.0.tag + html/* +untracked/docs/docs/manual/libsigc_manual.pdf (only if build-pdf=true) + html/* +untracked/MSVC_NMake/sigc.rc + sigc++config.h