office-gobmx/include/o3tl/any.hxx
Stephan Bergmann 7e403195e5 Introduce o3tl::optional as an alias for std::optional
...with a boost::optional fallback for Xcode < 10 (as std::optional is only
available starting with Xcode 10 according to
<https://en.cppreference.com/w/cpp/compiler_support>, and our baseline for iOS
and macOS is still Xcode 9.3 according to README.md).  And mechanically rewrite
all code to use o3tl::optional instead of boost::optional.

One immediate benefit is that disabling -Wmaybe-uninitialized for GCC as per
fed7c3deb3 "Slience bogus
-Werror=maybe-uninitialized" should no longer be necessary (and whose check
happened to no longer trigger for GCC 10 trunk, even though that compiler would
still emit bogus -Wmaybe-uninitialized for uses of boost::optional under
--enable-optimized, which made me ponder whether this switch from
boost::optional to std::optional would be a useful thing to do; I keep that
configure.ac check for now, though, and will only remove it in a follow up
commit).

Another longer-term benefit is that the code is now already in good shape for an
eventual switch to std::optional (a switch we would have done anyway once we no
longer need to support Xcode < 10).

Only desktop/qa/desktop_lib/test_desktop_lib.cxx heavily uses
boost::property_tree::ptree::get_child_optional returning boost::optional, so
let it keep using boost::optional for now.

After a number of preceding commits have paved the way for this change, this
commit is completely mechanical, done with

> git ls-files -z | grep -vz -e '^bin/find-unneeded-includes$' -e '^configure.ac$' -e '^desktop/qa/desktop_lib/test_desktop_lib.cxx$' -e '^dictionaries$' -e '^external/' -e '^helpcontent2$' -e '^include/IwyuFilter_include.yaml$' -e '^sc/IwyuFilter_sc.yaml$' -e '^solenv/gdb/boost/optional.py$' -e '^solenv/vs/LibreOffice.natvis$' -e '^translations$' -e '\.svg$' | xargs -0 sed -i -E -e 's|\<boost(/optional)?/optional\.hpp\>|o3tl/optional.hxx|g' -e 's/\<boost(\s*)::(\s*)(make_)?optional\>/o3tl\1::\2\3optional/g' -e 's/\<boost(\s*)::(\s*)none\>/o3tl\1::\2nullopt/g'

(before committing include/o3tl/optional.hxx, and relying on some GNU features).
It excludes some files where mention of boost::optional et al should apparently
not be changed (and the sub-repo directory stubs).  It turned out that all uses
of boost::none across the code base were in combination with boost::optional, so
had all to be rewritten as o3tl::nullopt.

Change-Id: Ibfd9f4b3d5a8aee6e6eed310b988c4e5ffd8b11b
Reviewed-on: https://gerrit.libreoffice.org/84128
Tested-by: Jenkins
Reviewed-by: Stephan Bergmann <sbergman@redhat.com>
2019-12-01 14:57:16 +01:00

325 lines
11 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */
/*
* This file is part of the LibreOffice project.
*
* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
*/
#ifndef INCLUDED_O3TL_ANY_HXX
#define INCLUDED_O3TL_ANY_HXX
#include <sal/config.h>
#include <cassert>
#include <type_traits>
#include <utility>
#include <o3tl/optional.hxx>
#include <com/sun/star/uno/Any.hxx>
#include <com/sun/star/uno/RuntimeException.hpp>
#include <com/sun/star/uno/Reference.hxx>
#include <com/sun/star/uno/XInterface.hpp>
#include <cppu/unotype.hxx>
#include <rtl/ustring.hxx>
#include <sal/types.h>
// Some functionality related to css::uno::Any that would ideally be part of
// <com/sun/star/uno/Any.hxx>, but (for now) cannot be for some reason.
namespace o3tl {
namespace detail {
struct Void {};
template<typename T> struct Optional { using type = T const *; };
template<> struct Optional<void> { using type = o3tl::optional<Void const>; };
template<> struct Optional<bool> { using type = o3tl::optional<bool const>; };
template<> struct Optional<sal_Int8> {
using type = o3tl::optional<sal_Int8 const>;
};
template<> struct Optional<sal_Int16> {
using type = o3tl::optional<sal_Int16 const>;
};
template<> struct Optional<sal_uInt16> {
using type = o3tl::optional<sal_uInt16 const>;
};
template<> struct Optional<sal_Int32> {
using type = o3tl::optional<sal_Int32 const>;
};
template<> struct Optional<sal_uInt32> {
using type = o3tl::optional<sal_uInt32 const>;
};
template<> struct Optional<sal_Int64> {
using type = o3tl::optional<sal_Int64 const>;
};
template<> struct Optional<sal_uInt64> {
using type = o3tl::optional<sal_uInt64 const>;
};
template<> struct Optional<float> {
using type = o3tl::optional<float const>;
};
template<> struct Optional<double> {
using type = o3tl::optional<double const>;
};
template<typename T> struct Optional<css::uno::Reference<T>> {
using type = o3tl::optional<css::uno::Reference<T> const>;
};
template<> struct Optional<css::uno::Reference<css::uno::XInterface>> {
using type = css::uno::Reference<css::uno::XInterface> const *;
};
template<typename> struct IsDerivedReference: std::false_type {};
template<typename T> struct IsDerivedReference<css::uno::Reference<T>>:
std::true_type
{};
template<> struct IsDerivedReference<css::uno::Reference<css::uno::XInterface>>:
std::false_type
{};
template<typename> struct IsUnoSequenceType: std::false_type {};
template<typename T> struct IsUnoSequenceType<cppu::UnoSequenceType<T>>:
std::true_type
{};
template<typename T> inline o3tl::optional<T const> tryGetConverted(
css::uno::Any const & any)
{
T v;
return (any >>= v)
? o3tl::optional<T const>(std::move(v)) : o3tl::optional<T const>();
}
}
/** Try to access the value of a specific type stored in an Any.
In trying to obtain a value, the same set of conversions as supported by
">>=" are considered.
The returned object is a proxy. Proxies can be either positive or negative.
Each proxy can be contextually converted to bool, yielding true iff the
proxy is positive. For a positive proxy P representing a value of requested
type T, for any T other than void, the expression *P yields that value of
type T. (Technically, the proxy is either a plain pointer or a
o3tl::optional, depending on whether a plain pointer into the given Any can
be returned for the specified type.)
@attention A proxy returned from this function must not outlive the
corresponding Any passed into this function (as it may constitute a pointer
into the Any's internals). That is the reason why this function is
restricted to lvalue arguments (i.e., to non-temporary Any objects), to
avoid misuses like
@code
css::uno::Any f();
if (auto p = o3tl::tryAccess<css::beans::NamedValue>(f())) {
return p->Name;
}
@endcode
@note Ideally this would be a public member function of css::uno::Any (at
least conditional on LIBO_INTERNAL_ONLY, as it requires C++11). However, as
std::optional (which would be needed to implement the proxies) is only
available since C++14, we need to use o3tl::optional for now. But To not
make every entity that includes <com/sun/star/uno/Any.hxx> depend on
boost_headers, keep this here for now.
@tparam T the C++ representation of a UNO type that can be contained in a
UNO ANY (i.e., any UNO type other than ANY itself). The legacy C++
representations sal_Bool, cppu::UnoVoidType, cppu::UnoUnsignedShortType,
cppu::UnoCharType, and cppu::UnoSequenceType are not supported. Must be a
complete type or void.
@param any an Any value.
@return a positive proxy for the value of the specified type obtained from
the given Any, or a negative proxy if no such value can be obtained.
*/
template<typename T> inline
typename std::enable_if<
!(detail::IsDerivedReference<T>::value
|| detail::IsUnoSequenceType<T>::value
|| std::is_base_of<css::uno::XInterface, T>::value),
typename detail::Optional<T>::type>::type
tryAccess(css::uno::Any const & any) {
// CHAR, STRING, TYPE, sequence types, enum types, struct types, exception
// types, and com.sun.star.uno.XInterface interface type:
return cppu::UnoType<T>::get().isAssignableFrom(any.getValueType())
? static_cast<T const *>(any.getValue()) : nullptr;
}
template<> inline detail::Optional<void>::type tryAccess<void>(
css::uno::Any const & any)
{
return any.hasValue()
? o3tl::optional<detail::Void const>()
: o3tl::optional<detail::Void const>(detail::Void());
}
template<> inline detail::Optional<bool>::type tryAccess<bool>(
css::uno::Any const & any)
{
return detail::tryGetConverted<bool>(any);
}
template<> inline detail::Optional<sal_Int8>::type tryAccess<sal_Int8>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_Int8>(any);
}
template<> inline detail::Optional<sal_Int16>::type tryAccess<sal_Int16>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_Int16>(any);
}
template<> inline detail::Optional<sal_uInt16>::type tryAccess<sal_uInt16>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_uInt16>(any);
}
template<> inline detail::Optional<sal_Int32>::type tryAccess<sal_Int32>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_Int32>(any);
}
template<> inline detail::Optional<sal_uInt32>::type tryAccess<sal_uInt32>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_uInt32>(any);
}
template<> inline detail::Optional<sal_Int64>::type tryAccess<sal_Int64>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_Int64>(any);
}
template<> inline detail::Optional<sal_uInt64>::type tryAccess<sal_uInt64>(
css::uno::Any const & any)
{
return detail::tryGetConverted<sal_uInt64>(any);
}
template<> inline detail::Optional<float>::type tryAccess<float>(
css::uno::Any const & any)
{
return detail::tryGetConverted<float>(any);
}
template<> inline detail::Optional<double>::type tryAccess<double>(
css::uno::Any const & any)
{
return detail::tryGetConverted<double>(any);
}
template<> detail::Optional<css::uno::Any>::type tryAccess<css::uno::Any>(
css::uno::Any const &) = delete;
template<> detail::Optional<sal_Bool>::type tryAccess<sal_Bool>(
css::uno::Any const &) = delete;
/*
// Already prevented by std::is_base_of<css::uno::XInterface, T> requiring T to
// be complete:
template<> detail::Optional<cppu::UnoVoidType>::type
tryAccess<cppu::UnoVoidType>(css::uno::Any const &) = delete;
template<> detail::Optional<cppu::UnoUnsignedShortType>::type
tryAccess<cppu::UnoUnsignedShortType>(css::uno::Any const &) = delete;
template<> detail::Optional<cppu::UnoCharType>::type
tryAccess<cppu::UnoCharType>(css::uno::Any const &) = delete;
*/
template<typename T> inline
typename std::enable_if<
detail::IsDerivedReference<T>::value,
typename detail::Optional<T>::type>::type
tryAccess(css::uno::Any const & any) {
return detail::tryGetConverted<T>(any);
}
template<typename T> typename detail::Optional<T>::type tryAccess(
css::uno::Any const volatile &&) = delete;
/** Access the value of a specific type stored in an Any, throwing an exception
on failure.
@attention A proxy returned from this function must not outlive the
corresponding Any passed into this function (as it may constitute a pointer
into the Any's internals). However, unlike with tryAccess, the benefit of
allowing this function to operate on temporaries appears to outweigh its
dangers.
@note Ideally this would be a public member function of css::uno::Any. See
tryAccess for details.
@tparam T the C++ representation of a UNO type that can be contained in a
UNO ANY. See tryAccess for details.
@param any an Any value.
@return a positive proxy for the value of the specified type obtained from
the given Any. See tryAccess for details.
@throws css::uno::RuntimeException when a value of the requested type
cannot be obtained.
*/
template<typename T> inline typename detail::Optional<T>::type doAccess(
css::uno::Any const & any)
{
auto opt = tryAccess<T>(any);
if (!opt) {
throw css::uno::RuntimeException(
OUString(
cppu_Any_extraction_failure_msg(
&any, cppu::UnoType<T>::get().getTypeLibType()),
SAL_NO_ACQUIRE));
}
return opt;
}
/** Access the value of a specific type stored in an Any, knowing the Any
contains a value of a matching type.
@attention A proxy returned from this function must not outlive the
corresponding Any passed into this function (as it may constitute a pointer
into the Any's internals). However, unlike with tryAccess, the benefit of
allowing this function to operate on temporaries appears to outweigh its
dangers.
@note Ideally this would be a public member function of css::uno::Any. See
tryAccess for details.
@tparam T the C++ representation of a UNO type that can be contained in a
UNO ANY. See tryAccess for details.
@param any an Any value.
@return a positive proxy for the value of the specified type obtained from
the given Any. See tryAccess for details.
*/
template<typename T> inline typename detail::Optional<T>::type forceAccess(
css::uno::Any const & any)
{
auto opt = tryAccess<T>(any);
assert(opt);
return opt;
}
}
#endif
/* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */