Giter Site home page Giter Site logo

optional's Introduction

optional

A library for representing optional (nullable) objects in C++.

optional<int> readInt(); // this function may return either an int or a not-an-int

if (optional<int> oi = readInt()) // did I get a real int
  cout << "my int is: " << *oi;   // use my int
else
  cout << "I have no int";

For more information refer to the documentation provided with this library.

optional's People

Contributors

akrzemi1 avatar beman avatar citrusmoose avatar dabrahams avatar danieljames avatar douggregor avatar eldiener avatar fcacciola avatar flamefire avatar grafikrobot avatar hkaiser avatar imikejackson avatar jensmaurer avatar jewillco avatar jhunold avatar jsoref avatar jzmaddock avatar kojoley avatar lastique avatar patak-dev avatar pdimov avatar petamas avatar robertleahy avatar sdarwin avatar steveire avatar straszheim avatar swatanabe avatar viboes avatar vinniefalco avatar vprus avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

optional's Issues

Uninitialized variable warning on gcc 8.3/release

gcc-8.3 in release mode reports an uninitialized variable warning in Boost.Beast:
https://travis-ci.org/boostorg/beast/jobs/519772855#L1557

This is the variable whose member gcc considers to be uninitialized:
https://github.com/boostorg/beast/blob/develop/include/boost/beast/websocket/impl/read.hpp#L667

I've been able to determine that it's optional's aligned_storage (https://github.com/boostorg/optional/blob/develop/include/boost/optional/detail/optional_aligned_storage.hpp#L29) that is causing trouble, because removing BOOST_MAY_ALIAS and undefining BOOST_OPTIONAL_DETAIL_USE_ATTRIBUTE_MAY_ALIAS makes the warning go away.

Reproduces with the following settings:
./b2 libs/beast/test/beast/websocket variant=release toolset=gcc-8.3 link=static cxxstd=17 -j2

`reset()` marked as deprecated

It should be a mistake that rest() of boost::optional is marked as deprecated because std::optional has reset() [optional.mod].

The story behind this finding

I am working on adding std::optional support for Spirit and it requires rewriting of optional handling. Currently it resets optional with boost::none and I wanted to generalize this (as I do not see a reason why it should handle boost and std optional differently) because I cannot reset std::optional with boost::none_t. The reset() method serves perfectly for this purpose, but the problem is that for some reason boost::optional has reset() marked as deprecated.

serialization for boost/optional

The boost serialization library includes an implementation for boost/optional. This breaks the general rule that serialization of boost components be implemented as part of that component and that only the boost serialization only contain implementations of serialization for std components. Now that there is a std::optional as part of C++17 we want to add another optional implementation to serialization. But on order to do that we want to move the current implementation here in order to "make room". I need to know if the maintainers of boost::optional are OK with this and will be willing to merge the PR. My inclination is to do this via a fork/pull request. Please let me know if this is all OK.

Cannot return non_const reference to contained value for uninitialized optional variable type.

I'm having an issue with the following code:

From boost/optional.hpp - lines 1267-1281 (problem lines marked with ~)

// Returns a reference to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
reference_const_type get() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }
~ reference_type get() { BOOST_ASSERT(this->is_initialized()) ; return this->get_impl(); }

/// Returns a copy of the value if this is initialized, 'v' otherwise
reference_const_type get_value_or ( reference_const_type v ) const { return this->is_initialized() ? get() : v ; }
reference_type get_value_or ( reference_type v ) { return this->is_initialized() ? get() : v ; }

/// Returns a pointer to the value if this is initialized, otherwise,
// the behaviour is UNDEFINED
// No-throw
pointer_const_type operator->() const { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }
~ pointer_type operator->() { BOOST_ASSERT(this->is_initialized()) ; return this->get_ptr_impl() ; }

The code returns non-const reference and pointer. These used for getting a reference to the contained variable holding the type presumably so it can be modified. (this is my case). BUT, the BOOST_ASSERT traps if the variable isn't initialized. This makes it impossible to modify the contained value. The is necessary in the context of the serialization library.

Syntax error in none_t.hpp

..\../boost/none_t.hpp:20:1: error: expected unqualified-id before '||' token
   20 | || defined(BOOST_NO_CXX11_LAMBDAS) || defined(BOOST_NO_CXX11_DECLTYPE_N3276) || defined(BOOST_NO_CXX11_NOEXCEPT) || defined(BOOST_NO_CXX11_DELETED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_FUNCTIONS) || defined(BOOST_NO_CXX11_DEFAULTED_MOVES) || defined(BOOST_NO_CXX11_EXPLICIT_CONVERSION_OPERATORS)
      | ^~

Looks like this file isn't covered by tests?

Define std::hash<boost::optional<T>> for compat with std::optional

[Edit] - title was updated, see comment 2 below:

Currently boost::optional<T> are not hashable, but std::optional<T> are.

boost::variant<Ts...> on the other hand is hashable. It seems fair that boost::optional<T> should have a hash_value ADL method.

Impl is fairly trivial, but it needs to be defined inside the boost namespace obviously so better to do it in Boost than in user code.

https://github.com/gcc-mirror/gcc/blob/edf8a7348075ec571536f44f9ae8c18bc1e02fed/libstdc%2B%2B-v3/include/std/optional#L1533

make_optional broken with optional references

c695be1 breaks this use-case.

Please see below for a minimal testcase.

#include <boost/optional.hpp>

struct Foo {};

Foo f;

Foo create_a_foo() {
    return {};
}

boost::optional<Foo&> frob() {
    return boost::make_optional<Foo&>(create_a_foo());
}

int main(){}

optional<X> fails to compile with VS2015 if X has an embedded enum named T

Example code:

struct STATUS
{
	enum T
	{
		DISCONNECTED,
		CONNECTING,
		CONNECTED,
	};

	T mValue;
};

void test_member_T()
{
  boost::optional<STATUS> x = STATUS();
  x->mValue = STATUS::CONNECTED;
  
  BOOST_TEST(x->mValue == STATUS::CONNECTED);
}

Compile error:

d:\boost\boost_git\boost/optional/optional.hpp(753): error C2838: '{dtor}': illegal qualified name in member declaration

d:\boost\boost_git\boost/optional/optional.hpp(753): note: while compiling class template member function 'void boost::optional_detail::optional_base<T>::destroy_impl(void)'
        with
        [
            T=STATUS
        ]
d:\boost\boost_git\boost/optional/optional.hpp(739): note: see reference to function template instantiation 'void boost::optional_detail::optional_base<T>::destroy_impl(void)' being compiled
        with
        [
            T=STATUS
        ]
d:\boost\boost_git\boost/optional/optional.hpp(831): note: see reference to class template instantiation 'boost::optional_detail::optional_base<T>' being compiled
        with
        [
            T=STATUS
        ]
test\optional_test_member_T.cpp(34): note: see reference to class template instantiation 'boost::optional<STATUS>' being compiled
d:\boost\boost_git\boost/optional/optional.hpp(753): error C2274: 'function-style cast': illegal as right side of '.' operator

unqualified call to `get<T>` with a non-`boost::optional` type should not match

boost::get<T>(boost::optional<T> ...) overload matches for a non-boost::optional type when boost namespace is associated with argument's type of unqualified call to get<T>.

template <typename U>
struct X {};

template <typename T, typename U>
inline int get(X<U> const&) { return 0; }

namespace boost {
    struct any_type_in_boost_namespace {};
}

#include <boost/optional.hpp>

class tag;

int main()
{
    get<tag>(X<boost::any_type_in_boost_namespace>{});
}

https://godbolt.org/z/14d476

The example obviously should compile, but instead it tries to instantiate boost::optional<tag> and fails the compilation.

Forwarding ref. and variadic make_optional overloads missing

The stdlib provides forwarding ref. overloads and variadic template overloads for make_optional:
http://en.cppreference.com/w/cpp/utility/optional/make_optional

The same is missing from boost::optional at least from what I can tell (correct me if I'm wrong).

All I could find here are these two overloads:

optional<T> make_optional ( T const& v )
optional<T> make_optional ( bool cond, T const& v )

Which is sub-optimal since now users expecting a move will end up doing a copy instead:

boost::make_optional(std::move(bigObject)); // oops, calls T const& overload making a copy

cc @K-ballo

Massive compilation time degradation when upgrading to libBoost 1.68

After upgrading to libBoost 1.68 our compilation time of our project (3.1 m lines) deceased dramatically from ~45 min to ~1h 10min.

Deeper investigation points to this commit:

commit 71d797b9ee132b381c2d4f3b5bcca2078b0a5062
Author: Andrzej Krzemienski <[email protected]>
Date:   Thu Jun 28 23:27:42 2018 +0200

    added implementation and tests of flat_map()

Compilation time of single file changes from 0m35.891s to 1m29.625s.
Same file compiled under other versions:

1.72:  1m28.077s
1.69:  1m26.839s
1.68:  1m30.255s
1.67:  0m26.357s
1.66:  0m26.683s

Our project heavily utilize boost::optional.
Tested on GCC 6.4 and GCC 8.

Commenting out "flat_map" methods reduces compilation time from 1m31.631s to 0m35.455s, commenting out additionally "map" method reduces compilation time even more back to 1.67 level (0m27.002s).

Please optimize these functions or add ability to exclude them from compilation.

Use std::invoke for monadic interface

At the moment the functions map and flat_map use the function call syntax f(value()). This allows "only" global/static functions and function objects to be used. But it is not possible to use a member function of the wrapped type which would require different call syntax. Using std::invoke(f, value()) instead would lead to a more general interface. This was also proposed in P0798.
One drawback of this approach would be that (e. g. non-const/const) overloaded member functions weren't supported since their type couldn't be deferred (I think?). To support all the variations of no-ref/&/&&, const and noexcept, several new overloads would be needed. And even then, it may not work as expected (?).

Deprecation warnings for boost/core/swap.hpp

It seems that swap has recently made changes to the include path and boost/core/swap.hpp is no longer recommended. This is causing deprecation warnings in many places since optional is used all over. The following changes seem to fix the problem:

--- a/include/boost/optional/detail/optional_swap.hpp
+++ b/include/boost/optional/detail/optional_swap.hpp
@@ -13,7 +13,7 @@
 #ifndef BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
 #define BOOST_OPTIONAL_DETAIL_OPTIONAL_SWAP_AJK_28JAN2015_HPP
 
-#include <boost/core/swap.hpp>
+#include <boost/core/invoke_swap.hpp>
 #include <boost/optional/optional_fwd.hpp>
 
 namespace boost {
diff --git a/include/boost/optional/optional.hpp b/include/boost/optional/optional.hpp
index 56d50d7..6e6e10e 100644
--- a/include/boost/optional/optional.hpp
+++ b/include/boost/optional/optional.hpp
@@ -30,7 +30,7 @@
 #include <boost/core/addressof.hpp>
 #include <boost/core/enable_if.hpp>
 #include <boost/core/explicit_operator_bool.hpp>
-#include <boost/core/swap.hpp>
+#include <boost/core/invoke_swap.hpp>
 #include <boost/optional/bad_optional_access.hpp>
 #include <boost/static_assert.hpp>
 #include <boost/throw_exception.hpp>

C++98 GCC 8 assignment does nothing

GCC 8.1.0/8.2.0/9.0.0 g++ -std=c++98 fails, g++ -std=c++11 is fine.
The problem is not presented on GCC 7.3.0.

MWE:

#include <boost/detail/lightweight_test.hpp>
#include <boost/optional.hpp>

int main()
{
  boost::optional<int> a, b(1);
  BOOST_TEST(!a);
  BOOST_TEST(!!b);
  a = b;
  BOOST_TEST(!!a); // Fails on GCC 8 -std=c++98

  return boost::report_errors();
}

https://wandbox.org/permlink/UPpKB0gpchSAaW61

Incorrect configuration for Intel Compiler GCC version

#elif BOOST_WORKAROUND(BOOST_GCC_VERSION, < 40600)

BOOST_GCC_VERSION is not defined when using the Intel compiler but instead BOOST_INTEL_GCC_VERSION should also be checked for the workaround.

If the Intel GCC version is too old then we get compilation failures as BOOST_OPTIONAL_DETAIL_NO_DEFAULTED_MOVE_FUNCTIONS is not defined. An example is compiling with Intel compilers on Redhat/CentOS 6 targets.

Uninitialized scalar field (UNINIT_CTOR) in tc_optional_base

This showed up on a Coverity Scan run in Boost.DateTime:

boost/optional/detail/optional_trivially_copyable_base.hpp: 

 protected:
 15    typedef T &       reference_type ;
 16    typedef T const&  reference_const_type ;
 17#ifndef  BOOST_OPTIONAL_DETAIL_NO_RVALUE_REFERENCES
 18    typedef T &&  rval_reference_type ;
 19    typedef T &&  reference_type_of_temporary_wrapper ;
 20#endif
 21    typedef T *         pointer_type ;
 22    typedef T const*    pointer_const_type ;
 23    typedef T const&    argument_type ;
 24
 25    tc_optional_base()
 26      :
   	
CID 202344 (#1-3 of 3): Uninitialized scalar field (UNINIT_CTOR)
2. uninit_member: Non-static class member m_storage is not initialized in this constructor nor in any functions that it calls.
 27      m_initialized(false) {}
 28
 29    tc_optional_base ( none_t )
 30      :
 31      m_initialized(false) {}
 32
 33    tc_optional_base ( argument_type val )

Coverity Scan issue id:

https://scan4.coverity.com/reports.htm#v17121/p13946/fileInstanceId=35326295&defectInstanceId=6591221&mergedDefectId=202344

CI test on Microsoft Windows

It would be interesting to add CI testing on Windows. In particular, boostorg/url may have discovered a bug in MSVC 14.1, 32-bit. Of course also checking the newer 14.2, 14.3 .

Missing #include's for in_place_factory when compiling for CUDA with clang

I'm not sure if this is an optional or Boost.Format issue, but I suspect this belongs here.

The issue is that some optional methods use in_place_factory as an argument to is_base_of which absolutely requires a complete type as argument, but so far as I can see in_place_factory is only ever forward declared.

When compiling for CUDA with clang this leads to:

In file included from <source>:14:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/format.hpp:38:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/format/internals.hpp:21:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/optional.hpp:15:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:43:
In file included from /opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_of.hpp:12:
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_and_derived.hpp:142:25: error: invalid application of 'sizeof' to an incomplete type 'boost::in_place_factory_base'
    BOOST_STATIC_ASSERT(sizeof(B) != 0);
                        ^~~~~~~~~
/opt/compiler-explorer/libs/boost_1_77_0/boost/static_assert.hpp:70:55: note: expanded from macro 'BOOST_STATIC_ASSERT'
#     define BOOST_STATIC_ASSERT( ... ) static_assert(__VA_ARGS__, #__VA_ARGS__)
                                                      ^~~~~~~~~~~
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_and_derived.hpp:217:41: note: in instantiation of template class 'boost::detail::is_base_and_derived_impl2<boost::in_place_factory_base, std::locale>' requested here
    BOOST_STATIC_CONSTANT(bool, value = bound_type::value);
                                        ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_of.hpp:25:31: note: in instantiation of template class 'boost::detail::is_base_and_derived_impl<boost::in_place_factory_base, std::locale>' requested here
            (::boost::detail::is_base_and_derived_impl<ncvB,ncvD>::value) ||
                              ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/type_traits/is_base_of.hpp:31:58: note: in instantiation of template class 'boost::detail::is_base_of_imp<boost::in_place_factory_base, std::locale>' requested here
      : public integral_constant<bool, (::boost::detail::is_base_of_imp<Base, Derived>::value)> {};
                                                         ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:794:32: note: in instantiation of template class 'boost::is_base_of<boost::in_place_factory_base, std::locale>' requested here
  : boost::conditional< boost::is_base_of<boost::in_place_factory_base, BOOST_DEDUCED_TYPENAME boost::decay<U>::type>::value
                               ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:823:25: note: in instantiation of template class 'boost::optional_detail::is_convertible_to_T_or_factory<std::locale, const std::locale &>' requested here
  : boost::conditional< is_convertible_to_T_or_factory<T, U>::value
                        ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/core/enable_if.hpp:41:41: note: in instantiation of template class 'boost::optional_detail::is_optional_val_init_candidate<std::locale, const std::locale &, false>' requested here
  struct enable_if : public enable_if_c<Cond::value, T> {};
                                        ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/optional.hpp:951:53: note: in instantiation of template class 'boost::enable_if<boost::optional_detail::is_optional_val_init_candidate<std::locale, const std::locale &, false>, bool>' requested here
                      BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
                                                    ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/format/format_implementation.hpp:40:44: note: while substituting deduced template arguments into function template 'optional' [with Expr = const std::locale &]
          exceptions_(io::all_error_bits), loc_(loc)
                                           ^
/opt/compiler-explorer/libs/boost_1_77_0/boost/optional/detail/optional_factory_support.hpp:32:9: note: forward declaration of 'boost::in_place_factory_base'
  class in_place_factory_base ;

You can see the issue here: https://godbolt.org/#g:!((g:!((g:!((h:codeEditor,i:(filename:'1',fontScale:14,fontUsePx:'0',j:1,lang:cuda,selection:(endColumn:23,endLineNumber:9,positionColumn:23,positionLineNumber:9,selectionStartColumn:23,selectionStartLineNumber:9,startColumn:23,startLineNumber:9),source:'%23include+%3Cboost/config.hpp%3E%0A//%0A//+These+%23undefs+reflect+the+current+state+of+Boost.Config+develop+compared+to+1.77:%0A//%0A%23undef+BOOST_NO_CXX11_VARIADIC_TEMPLATES%0A%23undef+BOOST_NO_VARIADIC_TEMPLATES%0A//%0A//+These+includes+are+required+to+make+this+compile,%0A//+uncomment+to+remove+the+errors:%0A//%0A//%23include+%3Cboost/utility/in_place_factory.hpp%3E%0A//%23include+%3Cboost/utility/typed_in_place_factory.hpp%3E%0A%0A%23include+%3Cboost/format.hpp%3E%0A'),l:'5',n:'0',o:'CUDA+C%2B%2B+source+%231',t:'0')),k:63.22701688555347,l:'4',n:'0',o:'',s:0,t:'0'),(g:!((g:!((h:compiler,i:(compiler:cuclang1100,filters:(b:'0',binary:'1',commentOnly:'0',demangle:'0',directives:'0',execute:'1',intel:'0',libraryCode:'0',trim:'1'),flagsViewOpen:'1',fontScale:14,fontUsePx:'0',j:1,lang:cuda,libs:!(),options:'-std%3Dc%2B%2B14+-O3+-I/opt/compiler-explorer/libs/boost_1_77_0/',selection:(endColumn:1,endLineNumber:1,positionColumn:1,positionLineNumber:1,selectionStartColumn:1,selectionStartLineNumber:1,startColumn:1,startLineNumber:1),source:1,tree:'1'),l:'5',n:'0',o:'clang+11.0.0+sm_75+CUDA-10.2+(CUDA+C%2B%2B,+Editor+%231,+Compiler+%231)',t:'0')),header:(),k:43.667751209994,l:'4',m:50,n:'0',o:'',s:0,t:'0'),(g:!((h:output,i:(compiler:1,editor:1,fontScale:12,fontUsePx:'0',wrap:'1'),l:'5',n:'0',o:'Output+of+clang+11.0.0+sm_75+CUDA-10.2+(Compiler+%231)',t:'0')),header:(),l:'4',m:50,n:'0',o:'',s:0,t:'0')),k:36.77298311444653,l:'3',n:'0',o:'',t:'0')),l:'2',m:100,n:'0',o:'',t:'0')),version:4

Adding

#include <boost/utility/in_place_factory.hpp>
#include <boost/utility/typed_in_place_factory.hpp>

Before including optional.hpp fixes the issue.

Why is the ctor of optional<T&> explicit?

I mean the ctor template <class U> explicit optional(const optional<U&>& rhs). It doesn't seem to have much sense - optional<T&> is logically a reference and it seems reasonable to allow it to be converted implicitly if the underlying pointer types allow this.
With the current implementation the usage of optional references can be cumbersome, because even the non-const-ref to const-ref conversion has to be explicit.

Forward constructors in boost::optional

I wasn't able to construct optional<string> from cons char * implicitly.

#include <string>
#include <boost/optional.hpp>

void f (const boost::optional<std::string>& a) {
}

int main() {
    f("amir");
}

The following compilation error apears:

opt.cpp: In function ‘int main()’:
opt.cpp:8:13: error: invalid initialization of reference of type ‘const boost::optional<std::__cxx11::basic_string<char> >&’ from expression of type ‘const char*’
     f("amir");
             ^
opt.cpp:4:6: note: in passing argument 1 of ‘void f(const boost::optional<std::__cxx11::basic_string<char> >&)’
 void f (const boost::optional<std::string>& a) {

I was wondering whether there is any way to fix it or it's a bug?

implicit constructor not working

calls to f3 and f4 do not compile:
https://godbolt.org/z/K4c1edTK3

#include <optional>
#include <string_view>
#include <boost/optional.hpp>
#include <boost/utility/string_view.hpp>

void f1( std::optional< std::string_view > ) {}
void f2( std::optional< boost::string_view > ) {}
void f3( boost::optional< std::string_view > ) {}
void f4( boost::optional< boost::string_view > ) {}

int main()
{
    f1("hello");
    f2("hello");
    f3("hello");
    f4("hello");
}

in_place_init & friends could be constexpr to enforce constant initialization

In https://github.com/boostorg/optional/blob/develop/include/boost/optional/optional.hpp#L93-L106, we have:

struct in_place_init_t
{
  struct init_tag{};
  explicit in_place_init_t(init_tag){}
};
const in_place_init_t in_place_init ((in_place_init_t::init_tag()));

struct in_place_init_if_t
{
  struct init_tag{};
  explicit in_place_init_if_t(init_tag){}
};
const in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));

This results in static initializers in binaries (although trivial ones). Instead, it should be valid to change their definition to the following, which would definitely get rid of static initializers in >= C++11:

struct in_place_init_t
{
  struct init_tag{};
  BOOST_CONSTEXPR explicit in_place_init_t(init_tag){}
};
BOOST_CONSTEXPR_OR_CONST in_place_init_t in_place_init ((in_place_init_t::init_tag()));

struct in_place_init_if_t
{
  struct init_tag{};
  BOOST_CONSTEXPR explicit in_place_init_if_t(init_tag){}
};
BOOST_CONSTEXPR_OR_CONST in_place_init_if_t in_place_init_if ((in_place_init_if_t::init_tag()));

"inline" linkage necessary

The following lines in optional.hpp should have "inline" linkage. This is necessary for using <boost/optional/optional.hpp> in a module.

    const in_place_init_t in_place_init((in_place_init_t::init_tag()));

   const in_place_init_if_t
       in_place_init_if((in_place_init_if_t::init_tag()));

Broken backward compability: libBoost 1.66 -> libBoost 1.67

Problematic code:

#include <boost/optional/optional.hpp>

struct A
{
    A(int a) : a(a) {}

    int a;
};

 #define TRUE 1

int main()
{
    return boost::optional<A>(TRUE , 5)->a;
}

libBoost 1.66 calls here:
optional ( bool cond, rval_reference_type val )
boost::optional(1, A(5));
and returns 5,

libBoost 1.67 and newer calls here:
template
explicit optional ( Expr&& expr,
BOOST_DEDUCED_TYPENAME boost::enable_if< optional_detail::is_optional_val_init_candidate<T, Expr>, bool>::type = true
)
and returns 1.

This is change of behavior without any warring.

IO error should be a warning

I am using Boost.Optional, and, while I do want to "include it in an output", the library which I am doing so has another mechanism to do so.

Translation, for Optional purposes, the following assertion should be a warning, IMO, and not an error:

BOOST_STATIC_ASSERT_MSG(sizeof(CharType) == 0, "If you want to output boost::optional, include header <boost/optional/optional_io.hpp>");

Specifically, I am handling "stringification" of the Optional for Catch unit test purposes, for which I have a String Maker setup for what I am doing.

Unless, mind you, it really is an error-error and should be covered, in which case, I suppose, yes, reporting an error assertion is appropriate.

That being said, when I ensure that the String Maker is included, the compiler is smart enough to detect this and it does not assert.

At the very least I do not think that the "error" should be quite as strong; i.e. when there are clearly alternatives to filling the output gap.

construction, comparisons broken

Lines 14 and 15 do not compile:
https://godbolt.org/z/cejhMT6z8

#include <optional>
#include <string_view>
#include <boost/optional.hpp>
#include <boost/utility/string_view.hpp>

int main()
{
    int n = 0;

    std::optional<std::string_view> v1 = "test";
    if( v1 == "test" )
        n |= 1;

    boost::optional<std::string_view> v2 = "test";
    if( v2 == "test ")
        n |= 2;

    return n;
}

optional is "is_copy_constructible" when T is not.

Hi.
I encountered issues while trying to use std::vector<boost::optional<std::tuple<NonCopyable, std::function<...>>>. THis failed to compile on msvc.

Looks like it boiled down to this repro: https://godbolt.org/g/cFNcUN

#include <boost/optional.hpp>
#include <type_traits>
#include <optional>

struct NonCopyAble
{
    NonCopyAble() = default;

    NonCopyAble(const NonCopyAble&) = delete;
    NonCopyAble& operator=(const NonCopyAble&) = delete;

    NonCopyAble(NonCopyAble&&) = default;
    NonCopyAble& operator=(NonCopyAble&&) = default;
};

static_assert(!std::is_copy_constructible<NonCopyAble>::value, "NonCopyAble is_copy_constructible when shouldn't be");
static_assert(!std::is_copy_constructible<std::optional<NonCopyAble>>::value, "std::optional<NonCopyAble> is_copy_constructible when shouldn't be");    
static_assert(!std::is_copy_constructible<boost::optional<NonCopyAble>>::value, "boost::optional<NonCopyAble> is_copy_constructible when shouldn't be");    // This assert fails

optional<const string &>::value_or returns reference to temp

I'm using boost::optional<const string &> and found some pitfalls when using value_or(char *).

Basically since value_or takes the "or" party as a template type the conversion from char * to string happens inside the function call and then a reference to that temporary is returned, leading to UB and in my case a crash.

Furthermore, even if the optional is populated and the alternative isn't use, it seems that some sort of copy of the value is still required because of the use of the ?: and then a similar crash occurs.

I think a reasonable workaround would be to have the value_or for references take the alternative value (r) only as const T & instead of as a type param. This would require the implicit conversion to happen at the call site and the function would not create a temporary.

This doesn't avoid all possible dangling references but it improves things.

Here is a short reproduction. I'm using boost 1.69, gcc 8.2:

#include <iostream>
#include <cstdlib>
#include <boost/optional.hpp>

int main()
{
    const std::string input = "a good string";
    boost::optional<const std::string &> opt = input;

    std::string output = opt.value_or("alternative");  // segfault here

    std::cout << output << std::endl;
}

Note I do get a warning about returning a reference to a temporary. But usually we disable warnings within boost because there's so much noise.

Fix used of 0 as nullptr to avoid this warning -Wzero-as-null-pointer-constant

Hi,
I'm compiling with -Werror,-Wzero-as-null-pointer-constant in clang-5.0.0 and getting

/Users/viboes/github/modular-boost3/boost/optional/detail/optional_reference_spec.hpp:139:172: error: zero as null pointer constant [-Werror,-Wzero-as-null-pointer-constant]
      optional(U& rhs, BOOST_DEDUCED_TYPENAME boost::enable_if_c<detail::is_same_decayed<T, U>::value && !detail::is_const_integral_bad_for_conversion<U>::value>::type* = 0) BOOST_NOEXCEPT
                                                                                                                                                                           ^
                                                                                                                                                                           nullptr

Please, could you fix it.
Vicente

Interoperability with std::optional<bool>

I have encountered unexpected results when assigning from an empty std::optional<bool> to a boost::optional<bool>. Instead of getting an empty optional, I find that the result is an optional populated with a value of false.

In the reverse scenario, assignment from boost::optional<bool> to std::optional<bool> fails to compile. Compilation failure may be preferable to unexpected results at runtime.

This is illustrated with the following example:

#include <optional>
#include <boost/optional.hpp>
#include <cassert>

boost::optional<bool> getB()
{
    return {};
}

std::optional<bool> getS()
{
    return {};
}

int main()
{
    std::optional<bool> s;
    boost::optional<bool> b;
    assert(!s);
    assert(!b);

    // s = getB(); // Fails to compile (good)
    b = getB();
    assert(!s);
    assert(!b);

    s = getS();
    b = getS(); // Want compile time error here
    assert(!s);
    assert(!b); // Runtime failure, bad
}

I was able to patch my local installation (Boost 1.77) to get the desired compilation error.

--- optional.hpp.orig   2021-10-29 21:50:41.000000000 +0100
+++ optional.hpp        2021-11-18 16:58:15.021204511 +0000
@@ -997,6 +997,12 @@
     BOOST_DEDUCED_TYPENAME boost::enable_if<optional_detail::is_optional_val_init_candidate<T, Expr>, optional&>::type
     operator= ( Expr&& expr )
       {
+        static_assert(!(
+            std::is_same<T, bool>() && std::is_same<Expr, std::optional<bool>&>()
+            ), "Assignment from std::optional<bool> not permitted");
+        static_assert(!(
+            std::is_same<T, bool>() && std::is_same<Expr, std::optional<bool>>()
+            ), "Assignment from std::optional<bool> not permitted");
         this->assign_expr(boost::forward<Expr>(expr),boost::addressof(expr));
         return *this ;
       }

Types other than bool already fail to compile. It's only optional<bool> interoperability that's an issue.

Would it be appropriate to adopt this change in boost::optional? It would be an API break. Alternatively, generating a warning in this situation may be useful and would avoid an API break. Is there a static_warn to complement static_assert?

Hard to find docs for the monadic functions

As far as I can tell, the monadic functions value_or(), map(), and flat_map(), don't have usable documentation pages.

They're only documented within a reference-type Optional Values page, but that page is not listed on the main page's table of contents at all. I can only find it by clicking the next-arrow on each page until I finally get there.

Because boost::optional does not use the same monadic function names as std::optional does, I find myself often having to search for these, to figure out which one is the equivalent of and_then() vs. transform().

It would be nice if the main page's ToC listed this reference page, and perhaps had an explicit link to "Monadic Functions" too, or some such.

MSVC-12 fails to generate defaulted functions

The issue appeared in Boost.Log tests. Apparently, MSVC-12 cannot generate defaulted move constructor and assignment operator:

D:\teeks99-09\run\boost_root\boost/optional/optional.hpp(968) : error C2610: 'boost::optional<T>::optional(boost::optional<T> &&)' : is not a special member function which can be defaulted
        D:\teeks99-09\run\boost_root\boost/optional/optional.hpp(1353) : see reference to class template instantiation 'boost::optional<T>' being compiled
D:\teeks99-09\run\boost_root\boost/optional/optional.hpp(1045) : error C2610: 'boost::optional<T> &boost::optional<T>::operator =(boost::optional<T> &&)' : is not a special member function which can be defaulted

This results in build failures.

-Wuninitialized warning on current gcc

It seems that the -Wuninitalized warning which supposedly has been fixed is still active under certain conditions even on gcc trunk:
godbolt

#include <boost/optional.hpp>

boost::optional<int> bla()
{
    return {};
}

bool blub()
{
    return bla().has_value();
}

Is this an issue of gcc or boost::optional?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.