diff options
-rw-r--r-- | comphelper/CppunitTest_comphelper_variadictemplates_test.mk | 33 | ||||
-rw-r--r-- | comphelper/Module_comphelper.mk | 1 | ||||
-rw-r--r-- | comphelper/qa/unit/variadictemplates.cxx | 234 | ||||
-rw-r--r-- | desktop/source/deployment/dp_services.cxx | 1 | ||||
-rw-r--r-- | include/comphelper/servicedecl.hxx | 70 | ||||
-rw-r--r-- | include/comphelper/unwrapargs.hxx | 164 | ||||
-rw-r--r-- | sc/source/ui/vba/vbaworkbook.cxx | 1 |
7 files changed, 370 insertions, 134 deletions
diff --git a/comphelper/CppunitTest_comphelper_variadictemplates_test.mk b/comphelper/CppunitTest_comphelper_variadictemplates_test.mk new file mode 100644 index 000000000000..21e8753f6605 --- /dev/null +++ b/comphelper/CppunitTest_comphelper_variadictemplates_test.mk @@ -0,0 +1,33 @@ +# -*- Mode: makefile-gmake; tab-width: 4; indent-tabs-mode: t -*- +# +# 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/. +# + +$(eval $(call gb_CppunitTest_CppunitTest,comphelper_variadictemplates_test)) + +$(eval $(call gb_CppunitTest_add_exception_objects,comphelper_variadictemplates_test, \ + comphelper/qa/unit/variadictemplates \ +)) + +$(eval $(call gb_CppunitTest_use_api,comphelper_variadictemplates_test, \ + udkapi \ + offapi \ +)) + +$(eval $(call gb_CppunitTest_use_externals,comphelper_variadictemplates_test, \ + boost_headers \ +)) + +$(eval $(call gb_CppunitTest_use_libraries,comphelper_variadictemplates_test, \ + comphelper \ + cppuhelper \ + cppu \ + sal \ + $(gb_UWINAPI) \ +)) + +# vim: set noet sw=4 ts=4: diff --git a/comphelper/Module_comphelper.mk b/comphelper/Module_comphelper.mk index 75d7c2adb761..acd50c6827be 100644 --- a/comphelper/Module_comphelper.mk +++ b/comphelper/Module_comphelper.mk @@ -29,6 +29,7 @@ $(eval $(call gb_Module_add_subsequentcheck_targets,comphelper,\ $(eval $(call gb_Module_add_check_targets,comphelper,\ CppunitTest_comphelper_syntaxhighlight_test \ + CppunitTest_comphelper_variadictemplates_test \ CppunitTest_comphelper_test \ )) diff --git a/comphelper/qa/unit/variadictemplates.cxx b/comphelper/qa/unit/variadictemplates.cxx new file mode 100644 index 000000000000..78f3bd7c3a42 --- /dev/null +++ b/comphelper/qa/unit/variadictemplates.cxx @@ -0,0 +1,234 @@ +/* -*- 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/. + */ + +#include <boost/optional.hpp> +#include <sal/types.h> +#include <comphelper/unwrapargs.hxx> +#include <comphelper/servicedecl.hxx> +#include "cppunit/TestAssert.h" +#include "cppunit/TestFixture.h" +#include "cppunit/extensions/HelperMacros.h" +#include "cppunit/plugin/TestPlugIn.h" + +#include <sstream> + +class VariadicTemplatesTest : public CppUnit::TestFixture +{ +public: + void testUnwrapArgs(); + void testServiceDecl(); + + CPPUNIT_TEST_SUITE(VariadicTemplatesTest); + CPPUNIT_TEST(testUnwrapArgs); + CPPUNIT_TEST(testServiceDecl); + CPPUNIT_TEST_SUITE_END(); +}; + +namespace { + +namespace detail { + +template <typename T> +inline void extract( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> const& seq, + sal_Int32 nArg, T & v, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> + const& xErrorContext ) +{ + if (nArg >= seq.getLength()) { + throw ::com::sun::star::lang::IllegalArgumentException( + OUString( "No such argument available!"), + xErrorContext, static_cast<sal_Int16>(nArg) ); + } + if (! (seq[nArg] >>= v)) { + OUStringBuffer buf; + buf.append( "Cannot extract ANY { " ); + buf.append( seq[nArg].getValueType().getTypeName() ); + buf.append( " } to " ); + buf.append( ::cppu::UnoType<T>::get().getTypeName() ); + buf.append( static_cast<sal_Unicode>('!') ); + throw ::com::sun::star::lang::IllegalArgumentException( + buf.makeStringAndClear(), xErrorContext, + static_cast<sal_Int16>(nArg) ); + } +} + +template <typename T> +inline void extract( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> const& seq, + sal_Int32 nArg, ::boost::optional<T> & v, + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> + const& xErrorContext ) +{ + if (nArg < seq.getLength()) { + T t; + extract( seq, nArg, t, xErrorContext ); + v = t; + } +} + +} // namespace detail + +template < typename T0, typename T1, typename T2, typename T3, typename T4 > +inline void unwrapArgsBaseline( + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const& seq, + T0& v0, T1& v1, T2& v2, T3& v3, T4& v4, + ::com::sun::star::uno::Reference< + ::com::sun::star::uno::XInterface> const& xErrorContext = + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>() ) +{ + ::detail::extract( seq, 0, v0, xErrorContext ); + ::detail::extract( seq, 1, v1, xErrorContext ); + ::detail::extract( seq, 2, v2, xErrorContext ); + ::detail::extract( seq, 3, v3, xErrorContext ); + ::detail::extract( seq, 4, v4, xErrorContext ); +} + +struct DummyStruct { + sal_uInt32 m_x; + + DummyStruct( sal_uInt32 x ): m_x( x ) { } + DummyStruct() : m_x( 0 ) { } + + void* getFactory( const char* ) const { + if( m_x == 42 ) + return new int( m_x ); + return nullptr; + } +}; + +} + +void VariadicTemplatesTest::testUnwrapArgs() { + OUString tmp1 = "Test1"; + sal_Int32 tmp2 = 42; + sal_uInt32 tmp3 = 42; + OUString tmp4 = "Test2"; + OUString tmp5 = "Test3"; + ::com::sun::star::uno::Any tmp6( + ::com::sun::star::uno::makeAny( tmp1 ) + ); + ::com::sun::star::uno::Any tmp7( + ::com::sun::star::uno::makeAny( tmp2 ) + ); + ::com::sun::star::uno::Any tmp8( + ::com::sun::star::uno::makeAny( tmp3 ) + ); + ::com::sun::star::uno::Any tmp9( + ::com::sun::star::uno::makeAny( tmp4 ) + ); + ::boost::optional< ::com::sun::star::uno::Any > tmp10( + ::com::sun::star::uno::makeAny( tmp5 ) + ); + ::boost::optional< ::com::sun::star::uno::Any > tmp11( + ::com::sun::star::uno::makeAny( tmp1 ) + ); + + // test equality with the baseline and template specialization with + // boost::optional< T > + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq1( + static_cast< sal_uInt32 >( 5 ) ); + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq2( + static_cast< sal_uInt32 >( 5 ) ); + + // tmp11 should be ignored as it is ::boost::optional< T > + ::comphelper::unwrapArgs( seq1, tmp6, tmp7, tmp8, tmp9, tmp10, tmp11 ); + unwrapArgsBaseline( seq2, tmp6, tmp7, tmp8, tmp9, tmp10 ); + ::com::sun::star::uno::Any* p1 = seq1.getArray(); + ::com::sun::star::uno::Any* p2 = seq2.getArray(); + + for( sal_Int16 i = 0; i < seq1.getLength() && i < seq2.getLength(); ++i ) { + CPPUNIT_ASSERT_MESSAGE( "seq1 and seq2 are equal", + p1[i] == p2[i] ); + } + CPPUNIT_ASSERT_MESSAGE( "seq1 and seq2 are equal", + seq1 == seq2 ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err ) { + std::stringstream ss; + ss << "IllegalArgumentException when unwrapping arguments at: " << + err.ArgumentPosition; + CPPUNIT_FAIL( ss.str() ); + } + + // test argument counting + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( + static_cast< sal_uInt32 >( 4 ) ); + ::comphelper::unwrapArgs( seq, tmp6, tmp7, tmp10, tmp11, tmp10, tmp6 ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err ) { + CPPUNIT_ASSERT_EQUAL( static_cast< short >( 5 ), err.ArgumentPosition ); + } + + OUString test1( "Test2" ); + OUString test2( "Test2" ); + OUString test3( "Test3" ); + OUString test4( "Test4" ); + OUString test5( "Test5" ); + + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( + static_cast< sal_uInt32 >( 4 ) ); + ::comphelper::unwrapArgs( seq, test1, test2, test3, test4, test5 ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err1 ) { + try { + ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > seq( + static_cast< sal_uInt32 >( 4 ) ); + unwrapArgsBaseline( seq, test1, test2, test3, test4, test5 ); + CPPUNIT_FAIL( "unwrapArgs failed while the baseline did not throw" ); + } + catch( ::com::sun::star::lang::IllegalArgumentException& err2 ) { + CPPUNIT_ASSERT_MESSAGE( "err1.ArgumentPosition == err2.ArgumentPosition", + err1.ArgumentPosition == err2.ArgumentPosition ); + } + } +} + +void VariadicTemplatesTest::testServiceDecl() { + DummyStruct dummy1( 42 ); + DummyStruct dummy2; + DummyStruct dummy3; + void* pRet = ::comphelper::service_decl::component_getFactoryHelper( "test", + dummy3, + dummy2, + dummy1 ); + + CPPUNIT_ASSERT_MESSAGE( "pRet != 0", + pRet != nullptr ); + + sal_uInt32* pnRet = static_cast< sal_uInt32* >( pRet ); + + CPPUNIT_ASSERT_MESSAGE( "*pnRet == 42", + *pnRet == 42 ); + delete pnRet; + + pRet = ::comphelper::service_decl::component_getFactoryHelper( "test", + dummy1, + dummy2, + dummy2 ); + + CPPUNIT_ASSERT_MESSAGE( "pRet != nullptr", + pRet != nullptr ); + + pnRet = static_cast< sal_uInt32* >( pRet ); + + CPPUNIT_ASSERT_MESSAGE( "*pnRet == 42", + *pnRet == 42 ); + + delete pnRet; +} + +CPPUNIT_TEST_SUITE_REGISTRATION(VariadicTemplatesTest); + +CPPUNIT_PLUGIN_IMPLEMENT(); + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/deployment/dp_services.cxx b/desktop/source/deployment/dp_services.cxx index 53ae196e4042..82b633b61206 100644 --- a/desktop/source/deployment/dp_services.cxx +++ b/desktop/source/deployment/dp_services.cxx @@ -18,7 +18,6 @@ */ -#define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 12 #include <comphelper/servicedecl.hxx> using namespace com::sun::star; diff --git a/include/comphelper/servicedecl.hxx b/include/comphelper/servicedecl.hxx index f9b0b12ddb01..b315e8e04ec5 100644 --- a/include/comphelper/servicedecl.hxx +++ b/include/comphelper/servicedecl.hxx @@ -24,10 +24,6 @@ #include <com/sun/star/uno/XComponentContext.hpp> #include <com/sun/star/lang/XServiceInfo.hpp> #include <uno/environment.h> -#include <boost/noncopyable.hpp> -#include <boost/preprocessor/cat.hpp> -#include <boost/preprocessor/repetition.hpp> -#include <boost/preprocessor/seq/enum.hpp> #include <functional> @@ -97,7 +93,7 @@ typedef ::std::function< In the latter case, somePostProcCode gets the yet unacquired "raw" pointer. */ -class COMPHELPER_DLLPUBLIC ServiceDecl : private ::boost::noncopyable +class COMPHELPER_DLLPUBLIC ServiceDecl { public: /** Ctor for multiple supported service names. @@ -107,6 +103,8 @@ public: @param pSupportedServiceNames supported service names @param cDelim delimiter for supported service names */ + ServiceDecl( const ServiceDecl& ) = delete; + ServiceDecl& operator=( const ServiceDecl& ) = delete; template <typename ImplClassT> ServiceDecl( ImplClassT const& implClass, char const* pImplName, @@ -148,12 +146,13 @@ template <bool> struct with_args; namespace detail { template <typename ImplT> class OwnServiceImpl - : public ImplT, - private ::boost::noncopyable + : public ImplT { typedef ImplT BaseT; public: + OwnServiceImpl( const OwnServiceImpl& ) = delete; + OwnServiceImpl& operator=( const OwnServiceImpl& ) = delete; OwnServiceImpl( ServiceDecl const& rServiceDecl, css::uno::Sequence<css::uno::Any> const& args, @@ -336,44 +335,31 @@ struct inheritingClass_ : public serviceimpl_base< detail::InheritingServiceImpl // component_... helpers with arbitrary service declarations: - -#define COMPHELPER_SERVICEDECL_getFactory(z_, n_, unused_) \ - if (pRet == 0) \ - pRet = BOOST_PP_CAT(s, n_).getFactory(pImplName); - -/** The following preprocessor repetitions generate functions like - - <pre> - inline void * component_getFactoryHelper( - sal_Char const* pImplName, - ServiceDecl const& s0, ServiceDecl const& s1, ... ); - </pre> - - which call on the passed service declarations. - - The maximum number of service declarations can be set by defining - COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS; its default is 8. -*/ -#define COMPHELPER_SERVICEDECL_make(z_, n_, unused_) \ -inline void * component_getFactoryHelper( \ - sal_Char const* pImplName, \ - BOOST_PP_ENUM_PARAMS(n_, ServiceDecl const& s) ) \ -{ \ - void * pRet = 0; \ - BOOST_PP_REPEAT(n_, COMPHELPER_SERVICEDECL_getFactory, ~) \ - return pRet; \ +template< typename T > +inline void* component_getFactoryHelper( const sal_Char* pImplName, void* pRet, + const T& s ) +{ + if( pRet == 0 ) + return s.getFactory( pImplName ); + return pRet; } -#ifndef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS -#define COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS 8 -#endif - -BOOST_PP_REPEAT_FROM_TO(1, COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS, - COMPHELPER_SERVICEDECL_make, ~) +template< typename T, typename... Args > +inline void* component_getFactoryHelper( const sal_Char* pImplName, void* pRet, + const T& s, const Args&... args ) +{ + if( pRet == 0 ) + return component_getFactoryHelper( pImplName, s.getFactory( pImplName ), args... ); + return pRet; +} -#undef COMPHELPER_SERVICEDECL_COMPONENT_HELPER_MAX_ARGS -#undef COMPHELPER_SERVICEDECL_make -#undef COMPHELPER_SERVICEDECL_getFactory +template< typename... Args > +inline void* component_getFactoryHelper( const sal_Char* pImplName, + const Args&... args ) +{ + void* pRet = 0; + return component_getFactoryHelper( pImplName, pRet, args... ); +} } // namespace service_decl } // namespace comphelper diff --git a/include/comphelper/unwrapargs.hxx b/include/comphelper/unwrapargs.hxx index 6c76f9dcbde4..af07ef66987c 100644 --- a/include/comphelper/unwrapargs.hxx +++ b/include/comphelper/unwrapargs.hxx @@ -22,114 +22,96 @@ #include <rtl/ustrbuf.hxx> #include <com/sun/star/uno/Sequence.hxx> +#include <com/sun/star/uno/XInterface.hpp> #include <com/sun/star/lang/IllegalArgumentException.hpp> -#include <boost/optional.hpp> -#include <boost/preprocessor/cat.hpp> -#include <boost/preprocessor/repetition.hpp> -#include <boost/preprocessor/arithmetic/add.hpp> #include <cppu/unotype.hxx> +#include <boost/optional.hpp> namespace comphelper { - -// generating helper functions to unwrap the service's argument sequence: - - /// @internal namespace detail { - -template <typename T> -inline void extract( - ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> const& seq, - sal_Int32 nArg, T & v, - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> - const& xErrorContext ) -{ - if (nArg >= seq.getLength()) { - throw ::com::sun::star::lang::IllegalArgumentException( - OUString( "No such argument available!"), - xErrorContext, static_cast<sal_Int16>(nArg) ); - } - if (! (seq[nArg] >>= v)) { - OUStringBuffer buf; - buf.append( "Cannot extract ANY { " ); - buf.append( seq[nArg].getValueType().getTypeName() ); - buf.append( " } to " ); - buf.append( ::cppu::UnoType<T>::get().getTypeName() ); - buf.append( static_cast<sal_Unicode>('!') ); + inline void unwrapArgsError( + const OUString& str, sal_Int32 nArg, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& xErrorContext = + ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >() ) + { throw ::com::sun::star::lang::IllegalArgumentException( - buf.makeStringAndClear(), xErrorContext, - static_cast<sal_Int16>(nArg) ); + str, xErrorContext, static_cast< sal_Int16 >( nArg ) ); } -} -template <typename T> -inline void extract( - ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any> const& seq, - sal_Int32 nArg, ::boost::optional<T> & v, - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface> - const& xErrorContext ) -{ - if (nArg < seq.getLength()) { - T t; - extract( seq, nArg, t, xErrorContext ); - v.reset( t ); + template< typename T, typename... Args > + inline void unwrapArgsError( const OUString& str, sal_Int32 nArg, T&, Args&... args ) + { + return unwrapArgsError( str, nArg, args... ); } -} - -} // namespace detail - -#define COMPHELPER_UNWRAPARGS_extract(z_, n_, unused_) \ - detail::extract( seq, n_, BOOST_PP_CAT(v, n_), xErrorContext ); -#define COMPHELPER_UNWRAPARGS_args(z_, n_, unused_) \ - BOOST_PP_CAT(T, n_) & BOOST_PP_CAT(v, n_) -/** The following preprocessor repetitions generate functions like + inline void unwrapArgs( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >&, + sal_Int32, + const ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface >& ) + { + return; + } - <pre> - template <typename T0, typename T1, ...> - inline void unwrapArgs( - uno::Sequence<uno::Any> const& seq, - T0 & v0, T1 & v1, ..., - css::uno::Reference<css::uno::XInterface> const& xErrorContext = - css::uno::Reference<css::uno::XInterface>() ); - </pre> - (full namespace qualification ::com::sun::star has been omitted - for brevity) + inline void unwrapArgs( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >&, + sal_Int32 ) + { + return; + } - which unwraps the passed sequence's elements, assigning them to the - referenced values. Specify optional arguments as boost::optional<T>. - If the length of the sequence is greater than the count of arguments, - then the latter sequence elements are ignored. - If too few arguments are given in the sequence and a missing argument is - no boost::optional<T>, then an lang::IllegalArgumentException is thrown - with the specified xErrorContext (defaults to null-ref). + template< typename T, typename... Args > + inline void unwrapArgs( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& seq, + sal_Int32 nArg, ::boost::optional< T >& v, Args&... args ); + + template< typename T, typename... Args > + inline void unwrapArgs( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& seq, + sal_Int32 nArg, T& v, Args&... args ) + { + if( seq.getLength() <= nArg ) + { + return unwrapArgsError( OUString( "No such argument available!"), + nArg, args... ); + } + if( ! ( seq[nArg] >>= v ) ) + { + OUStringBuffer buf; + buf.append( "Cannot extract ANY { " ); + buf.append( seq[nArg].getValueType().getTypeName() ); + buf.append( " } to " ); + buf.append( ::cppu::UnoType<T>::get().getTypeName() ); + buf.append( static_cast<sal_Unicode>('!') ); + return unwrapArgsError( buf.makeStringAndClear(), nArg, args... ); + } + return unwrapArgs( seq, ++nArg, args... ); + } - The maximum number of service declarations can be set by defining - COMPHELPER_UNWRAPARGS_MAX_ARGS; its default is 12. -*/ -#define COMPHELPER_UNWRAPARGS_make(z_, n_, unused_) \ -template < BOOST_PP_ENUM_PARAMS( BOOST_PP_ADD(n_, 1), typename T) > \ -inline void unwrapArgs( \ - ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any > const& seq, \ - BOOST_PP_ENUM(BOOST_PP_ADD(n_, 1), COMPHELPER_UNWRAPARGS_args, ~), \ - ::com::sun::star::uno::Reference< \ - ::com::sun::star::uno::XInterface> const& xErrorContext = \ - ::com::sun::star::uno::Reference< ::com::sun::star::uno::XInterface>() ) \ -{ \ - BOOST_PP_REPEAT(BOOST_PP_ADD(n_, 1), COMPHELPER_UNWRAPARGS_extract, ~) \ + template< typename T, typename... Args > + inline void unwrapArgs( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& seq, + sal_Int32 nArg, ::boost::optional< T >& v, Args&... args ) + { + if( nArg < seq.getLength() ) + { + T t; + unwrapArgs( seq, nArg, t, args... ); + v = t; + } else { + unwrapArgs( seq, ++nArg, args... ); + } + } } -#ifndef COMPHELPER_UNWRAPARGS_MAX_ARGS -#define COMPHELPER_UNWRAPARGS_MAX_ARGS 12 -#endif - -BOOST_PP_REPEAT(COMPHELPER_UNWRAPARGS_MAX_ARGS, COMPHELPER_UNWRAPARGS_make, ~) - -#undef COMPHELPER_UNWRAPARGS_MAX_ARGS -#undef COMPHELPER_UNWRAPARGS_make -#undef COMPHELPER_UNWRAPARGS_args -#undef COMPHELPER_UNWRAPARGS_extract +template< typename... Args > +inline void unwrapArgs( + const ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Any >& seq, + Args&... args ) +{ + return detail::unwrapArgs( seq, 0, args... ); +} } // namespace comphelper diff --git a/sc/source/ui/vba/vbaworkbook.cxx b/sc/source/ui/vba/vbaworkbook.cxx index 383ad1d72426..a7fc1ac49b70 100644 --- a/sc/source/ui/vba/vbaworkbook.cxx +++ b/sc/source/ui/vba/vbaworkbook.cxx @@ -19,6 +19,7 @@ #include <vbahelper/helperdecl.hxx> #include <tools/urlobj.hxx> +#include <boost/optional.hpp> #include <comphelper/unwrapargs.hxx> #include <comphelper/servicehelper.hxx> |