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 pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy