Giter Site home page Giter Site logo

optional's Introduction

Optional

A single-header header-only library for representing optional (nullable) objects for C++14 (and C++11 to some extent) and passing them by value. This is the reference implementation of proposal N3793 (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3793.html). Optional is now accepted into Library Fundamentals Technical Specification (see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3848.html). The interface is based on Fernando Cacciola's Boost.Optional library (see http://www.boost.org/doc/libs/1_52_0/libs/optional/doc/html/index.html)

Usage

optional<int> readInt(); // this function may return 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 usage examples and the overview see http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html

Supported compilers

Clang 3.2, Clang 3.4, G++ 4.7.2, G++ 4.8.1. Tested only with libstdc++, versions 20130531, 20120920, 20110428. Others have reported it also works with libc++.

Known Issues

  • Currently, the reference (and the only known) implementation of certain pieces of functionality explore what C++11 identifies as undefined behavior (see national body comment FI 15: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3770.html#FI15). This is mostly why Optional was removed from C++14 and put into Library Fundamentals TS. Luckily what the Standard identifies as UB is well defined on all known platforms. We expect that the C++14 wil fix this problem, so that our trick becomes well-defined.
  • In libstdc++ versions below 20130531 the constructor taking initializer_list argument is not constexpr. This is because initializer_list operations are not constexpr in C++11. This works however in version 20130531. It is also not enabled for libc++ because I do not have access to it and do not know if it provides constexpr initializer_list.
  • In G++ 4.7.2 and 4.8.0 member function value_or does not have rvalue reference overload. These compilers do not support rvalue overloding on *this.
  • In order for the library to work with slightly older compilers, we emulate some missing type traits. On some platforms we cannot correctly detect the available features, and attempts at workarounds for missing type trait definitions can cause compile-time errors. Define macro TR2_OPTIONAL_DISABLE_EMULATION_OF_TYPE_TRAITS if you know that all the necessary type traits are defined, and no emulation is required.

License

Distributed under the Boost Software License, Version 1.0.

optional's People

Contributors

akrzemi1 avatar ericsebesta avatar kubao avatar nabijaczleweli avatar randrewy avatar stbuehler avatar theassassin avatar vedgy 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  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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

optional's Issues

T::T(T&&) and T::operator=(T&&) are invoked directly by optional<T>, add to standard?

Say, we have a class whose invariant is to be always valid:

class File {
public:
    File() = delete;
    File(const char* filename, const char* mode); // throws on error
    [ copy/move ctors and assignments deleted ]
};

Note, that move constructor and assignment are deleted since a moved-out object would have to be invalid.

In case we need an object that is either or valid File or not, we can use optional<File>.

In case we need a movable optional<File> we do need to provide the deleted move constructor and assignment. If we add those as private methods and provide friend access to optional<File> the invariant of the plain File remains intact:

class File {
public:
    ...
private:
    friend class optional<File>;
    File(File&& x) {...}
    File& operator=(File&& x) {...}
};

This solution happens to work with your implementation of optional because these methods happen to be invoked by optional<> itself. If they were invoked by some intermediate helper class it would not work since the helper class should be specified as friend.

What do you think, is this a valid use case? If so, should this requirement of direct invocation of move constructors and assignments be added to the standard?

Does not work with Pybind11

According to https://pybind11.readthedocs.io/en/stable/advanced/cast/stl.html#c-17-library-containers, add optional type in pybind11 is simple as adding:

// `boost::optional` as an example -- can be any `std::optional`-like container
namespace pybind11 { namespace detail {
    template <typename T>
    struct type_caster<boost::optional<T>> : optional_caster<boost::optional<T>> {};
}}

But it fails to compile. I'm not a template person... so I switched to TartanLlama/optional and it works.

Support for sentinel values

Has the idea of supporting specializations for sentinel values ever been discussed? The only mention of it I could find was on r/cpp, so I'm not sure if it just hasn't been discussed, or if it has, but was rejected. If it is the former, would you be open to consider such a feature?

Copy-constructibility type trait not propagated from contained type

Here's a simple example showing that an optional<unique_ptr<int>> comes back as being copy_constructible, even though a unique_ptr<int> is not:

#include <vector>
#include <memory>
#include <type_traits>
#include "Optional/optional.hpp"

int main() {
    typedef std::unique_ptr<int> UniquePtrInt;
    typedef std::experimental::optional<UniquePtrInt> OptUniquePtrInt;

    OptUniquePtrInt foo;
    OptUniquePtrInt bar (foo); // FAILS

    static_assert(
        not std::is_copy_constructible<UniquePtrInt>::value,
         "UniquePtrInt is claiming to be copy constructible."
    );

     static_assert(
        not std::is_copy_constructible<OptUniquePtrInt>::value,
         "OptUniquePtrInt is claiming to be copy constructible."
     ); // FAILS
}

Same for other traits like is_copy_assignable. This creates problems for containing classes relying on knowing these traits for implementation choices.

Solving this with a "simple" SFINAE doesn't seem to work (of a std::enable_if controlled by is_copy_assignable on the copy constructor, for instance). But Daniel Krugler's xstd::optional seemed to have found a pattern to doing it. I don't know about what other issues it might have, but it was handling this particular case....as well as correctly propagating the trait if the type was copy constructible.

Why not to put clear() to the public scope?

It seems that currently there is no way to make the object null again after having a value. I think it makes sense to have clear() in public scope, or to have copy assignments to nullable objects.

Build failure on clang 3.5

$ clang++ -v
clang version 3.5.0 (tags/RELEASE_350/final)
Target: armv6l-unknown-linux-gnueabihf
Thread model: posix
Found candidate GCC installation: /usr/bin/../lib/gcc/armv6l-unknown-linux-gnueabihf/4.8.2
Found candidate GCC installation: /usr/lib/gcc/armv6l-unknown-linux-gnueabihf/4.8.2
Selected GCC installation: /usr/bin/../lib/gcc/armv6l-unknown-linux-gnueabihf/4.8.2
Candidate multilib: .;@m32
Selected multilib: .;@m32

I'm getting http://dpaste.com/38YQ0SB when running clang++ -c test_optional.cpp -std=c++11. The compiler-defined macros are at http://dpaste.com/0G69CY9 (that's the output of clang++ -dM -E -x c++ -std=c++11 /dev/null).

optional<T&> should have the assignment behavior of a T&

(Took a while to get this posted, but here is sort of my line of thinking.)

References cannot be default constructed or changed to point to a different address. So when assignment to one reference from another is performed, the value the right-hand reference points to is copied over the value in the left-hand reference:

int i1 = 1;
int i2 = 2;
int & ir1 = i1;
int & ir2 = i2;

ir1 = ir2;
cout << i1;  // Will output 2

Using std::experimental::optional gives a different result:

int i1 = 1;
int i2 = 2;
optional<int &> ir1 = i1;
optional<int &> ir2 = i2;

ir1 = ir2;
cout << i1;  // Will output 1

There has apparently been lengthy debate on the subject of whether optional references should act more like references in this case (copying their target values) or more like pointers (retargeting to the new reference). The conclusion is summarized here:

http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2013/n3527.html#optional_ref.rationale.assign

This statement is made:

Neither of these models appears more valid than the other.

Not having easy access to the full range of debate, I wanted to mention something that seems it would be addressed in that document but is not.

What I think tips the scale to where it is not all equal is that many cases of optional will come by introduction into existing codebases...perhaps they could be piecewise transforming a T into an optional<T>. In this light, the difference seen in my integer reference transformation above would be a source of error. Such sources of error can be big problems in large codebases attempting to leverage a new standard library feature. And of course, they get trickier if they're not source-level but in general-purpose abstractions, that used to work one way but now work differently.

If std::reference_wrapper did not exist, then perhaps there would be a stronger argument to have optional adopt this container-friendly behavior. Yet the composability of C++ is reliant upon the parts following predictable rules; and breaking those understandings leads to things like auto_ptr. I'd argue this case shows optional<T> deviating in its characteristics relative to T in a way that I think is beyond the scope of its proposal...and could be achieved other ways. Achieving a smoother transition from T to optional<T> cannot be achieved another way.

So it seems to me that the assignment of an optional reference to another should fail with a runtime error on nullopt source or target, and do a value copy assignment if they both contain a reference. If it's too late to consider such a change, then perhaps at least this line of argumentation could be addressed in the proposal...as it currently does not seem to be.

Abstract types cannot have optional references

I noticed this when trying out the optional references:

#include "Optional/optional.hpp"

using std::experimental::optional;

class foo {
    virtual void doSomething() = 0;
};

class bar : public foo {
    void doSomething() override {
    }
};

int main() {

    // This works...

    int i = 3;
    int & ir = i;
    optional<int &> oir = ir;

    // And so does this...

    bar b;
    foo & fr = b;
    bar & br = b;
    optional<bar &> obr = br;

    // But this does not...

    optional<foo &> ofr = fr;
}

The error that comes up is:

cannot allocate an object of abstract type ‘foo’ because the following virtual functions are pure within ‘foo’: virtual void foo::doSomething()

One is able to have raw references to an abstract type. So it would seem that an optional reference could be had to an abstract type as well?

Build breaks on Clang 3.4

For some reason, on OSX with clang3.4, the defines treat it as 3.5 and enable some constexpr functionality that's not supported there.

Extracting move-only values out of a std::experimental::optional

Thanks for the work on optional and posting the repository! I'd been using my own modification of boost to support move-only types. When I ran up against limitations I found Daniel Krugler's code and we worked out a couple cases in my codebase it couldn't handle. It sounds like he has now deferred to this codebase as being on track to sort the outstanding issues out.

So far it's done well in the situations I've got, some of which were tricky. But one feature I can't seem to find is how to extract the value out of an move-only valued optional.

Consider this small sample. (Note: Since it has a null state of its own, unique_ptr may not be the best example of a move-only type would be used with an optional, but it's well-known and the same principles would apply for any class with that property).

#include <iostream>

class PrintDestructor {
public:
    ~PrintDestructor () {
        std::cout << "Destructor is running\n";
    }
};

int main(int argc, char *argv[])
{
    auto optSmartPtr = std::experimental::make_optional(
        std::unique_ptr<PrintDestructor>(new PrintDestructor)
    );
    if (not optSmartPtr) {
        std::cout << "Initialization of optSmartPtr failed\n";
    }
    if (not (*optSmartPtr).get()) {
        std::cout << "Optional does not hold a non-null pointer\n";
    }
    std::unique_ptr<PrintDestructor> plainSmartPtr (std::move(*optSmartPtr));
    if (optSmartPtr) {
        std::cout << "The optional still believes it has a value\n";
        if ((*optSmartPtr).get() == nullptr) {
             std::cout << "The value it holds is a null pointer\n";
        } else {
            std::cout << "The value it holds is non-null\n";
        }
    } else {
        std::cout << "The optional contains nullopt\n";
    }
    return 0;
}

The output I get is:

The optional still believes it has a value
The value it holds is a null pointer
Destructor is running

The extract() operator I had would move the stored value out and make the optional empty. I don't think it's necessary if the implementation is guaranteed to work this way...if the move is able to work on the "guts of the optional". But one does have to remember that it doesn't automatically "disengage" the optional and you assign to nullopt afterward.

So the "issue" would be "should there be an extract operator that does that?" The "question" would be if the implementation is guaranteed to behave this way across all the spectrum of weird properties of types?

Thanks!!

Exception safety issue in copy/move constructors

** disclaimer: I'm new at this **

optional(const optional& rhs) 
  : OptionalBase<T>(only_set_initialized, rhs.initialized())
  {
    if (rhs.initialized()) new (dataptr()) T(*rhs);
  }

If rhs is initialized, and the copy constructor for T throws an exception then T will be destroyed even though it was never created.

Since OptionalBase's destructor is called even when an exception is thrown, OptionalBase will invoke the destructor on storage.value_.

This issue also appears in the move constructor.

"C'tor/d'tor is not implicitly called" error with Unreal Engine (VS 2017)

Hi,

Unfortunately akrzemi1::optional doesn't compile in Unreal Engine projects. It gives the following errors:

Error	C4582	'akrzemi1::storage_t<T>::value_': constructor is not implicitly called	MyTestProject	optional.hpp	270	
Error	C4583	'akrzemi1::storage_t<T>::value_': destructor is not implicitly called	MyTestProject	optional.hpp	275	

The lines in question are:

constexpr storage_t( trivial_init_t ) noexcept : dummy_() {};

and

  ~storage_t(){}

Outside of Unreal Engine projects, it of course works flawlessly. Unfortunately, Unreal Engine has its own build system (UBT), and it's very peculiar on how it uses Visual Studio. It's basically a VS 2017 project and uses the VS 2017 compiler, but in C++14 mode, with the compiler flags set by some Unreal Engine C# build scripts (yes, it's horrible...).

This issue arose in ThePhD/sol2 too: ThePhD/sol2#235. I think @ThePhD took the implementation of his optional from you, and modified it. He fixed it in this and this commit, with quite some extensive changes (which are beyond my C++ skills).

Now I would be interested in: Why does this occur (apparently) only when building akrzemi1::optional in Unreal Engine, which uses the VS 2017 compiler, so it should presumably work? What makes it fail? Could it be some peculiar compiler flag? Or is it a bug in akrzemi1::optional that @ThePhD fixed in his copy?

Build failure on Ubuntu 14.04

Ubuntu seems to use a patched version of clang which calls itself 3.4.0, but implements all the 3.4.2-specific features used by this library:

Ubuntu clang version 3.4-1ubuntu3 (tags/RELEASE_34/final) (based on LLVM 3.4)

#define __VERSION__ "4.2.1 Compatible Ubuntu Clang 3.4 (tags/RELEASE_34/final)"
#define __clang_major__ 3
#define __clang_minor__ 4
#define __clang_patchlevel__ 0
#define __clang_version__ "3.4 (tags/RELEASE_34/final)"

This leads to the redefinition of is_trivially_destructible and the others gated by TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_. The code compiles fine if TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_ is manually defined.

I'm not sure what would be a good way to detect this situation.

Iterators are missing?

Hi,

As Optional is conceptually similar to a vector or list with at most one element, I'd purpose to implement iterators. One benefit would be the support for lots of <algorithm> functions. Another one would be code like this:

for(auto x: o) {
   foo(x);
}

This code would support out-of-the-box this optional type without any modification.

The theoretical background is that optional is a functor (the mathematical functor and not a C++ functor) and a structure which can be traversed, like the Haskells Traversable or Foldable type class. Please have a look at this Wiki page: Traversable and Foldable for more infos.

As a fan of Haskell and C++, I'd love to be able to use some functional ideas in C++.

Thanks!

critique of arguments for n3672/rationale.moved_from

The n3672 / rationale.moved_from lists two performance reasons for backing the decision that the moved-from optional is not disengaged.

Traditionally C++ developers used to incorporate optionality into most types: nullable pointers, default-constructible resource types are still the norm.

The optional type could be used to build stricter and safer types by providing easy switching between the always-valid and maybe-valid versions of the same type.

Since the decision above may prevent using the optional type in those, important use cases I'd like to discuss the arguments that lead to this decision.

  1. The first argument is effectively stating that moving from and into an optional<T> where T doesn't have efficient move could be more efficient by saving a destruction and a (move-)construction.
  2. The second argument is that if T is trivially-copyable, then moving optional<T> can be reduced to a memcpy if the right-hand side of the move operation need not to be updated (destructed, disengaged).

I don't think either of these arguments should be given too much weight, because:

  • moving a type that doesn't have efficient move (first argument) is inefficient to move in the first place. The cost of the move is expected to be far more costly then the destruction or move-construction.
  • storing significant amount of data on the stack is not realistic. And once we're using the heap, moving is an O(1) operation. Compare this to the minor performance gain a trivial-copy can bring.
  • when writing performance-critical code one would never store data in an array of optional<int>'s (it would be probably array<int> + bitarray)

It's true that the standard allows the right-hand side of the move-assignment left in an unspecified state but it's just because an unspecified T type has unspecified semantics. The move semantics of a concrete type should follow from the semantics of the type. All movable types in the std namespace satisfy this and all do something with the rhs of the move, in particular the "least-surprising" thing. optional is a concrete type with specified semantics and even N3672 acknowledges that disengaging-after-move would be the least surprising thing to do:

The fact that the moved-from optional is not disengaged may look 'uncomfortable' at first, ...

constexpr moves

Optional is awesome and I'd like to return an optional<int> from a constexpr function. The following function compiles with g++ 5.2.0, but not with clang 3.7.0.

$ clang++ -std=c++1z -x c++ -c - <<< '
#include "optional.hpp"
constexpr std::experimental::optional<int> f1() { return 5; }
'

<stdin>:3:44: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
constexpr std::experimental::optional<int> f1() { return 5; }
                                           ^
<stdin>:3:51: note: non-constexpr constructor 'optional' cannot be used in a constant expression
constexpr std::experimental::optional<int> f1() { return 5; }
                                                  ^
./optional.hpp:424:3: note: declared here
  optional(optional&& rhs) noexcept(is_nothrow_move_constructible<T>::value)
  ^

I found a mention of this in the rationale:

[..] we know an efficient implementation of such optional with compile-time interface — except for copy constructor and move constructor — is possible.

If optionals can't be returned, their usefulness in constexpr functions seems unfortunately very limited to me.

As a temporary workaround, I tried adding constexpr to the move constructor, and both g++ and clang accepted it. Has the definition of constexpr functions been relaxed so that this is possible, or am I relying on overly permissible compilers?

Exactly equivalent to 17 optional? And license question

Hi, I'm seeking an optional implementation to include with my library, a C++14 reflective enum implementation. The library would automatically switch to std::optional if compiled with 17. I wanted to verify that a) this exactly mimics the optional that was standardized in terms of interface; the readme says it was the reference implementation during the proposal but I'm not sure if there were any further changes. And b) I wanted to verify that using optional in this way would be alright. Obviously would leave the license in place, my own library will probably be boost licensed too and of course would credit you appropriately. Considering either using this library or https://github.com/martinmoene/optional-lite, not sure what the difference is. Cheers.

License?

Wondering what the license on this code is. I've previously asked around, and a friend (@godbyk) asked STL, who asked Herb Sutter, regarding a make_unique implementation from the standard, and despite having written it they couldn't figure out the copyright or license terms.

Allow initialization of optionals from convertible type U (or optional<U>)

Currently it is possible to initialize one optional from another if their types match exactly. But one should ideally be able to initialize one optional from another if the types are convertible:

#include <memory>
#include "Optional/optional.hpp"

using std::experimental::optional;
using std::experimental::make_optional;
using std::shared_ptr;

int main() {
    shared_ptr<int> i (new int (1020));
    shared_ptr<int const> ic = i;

    optional<shared_ptr<int>> oi = i;
    optional<shared_ptr<int>> oi2 = oi;

    // Everything up to here works, but these fail...
    optional<shared_ptr<int const>> oic = i;
    optional<shared_ptr<int const>> oic2 = oi;
}

The error you get on oic is:

conversion from ‘std::shared_ptr<int>’ to non-scalar type ‘std::experimental::optional<std::shared_ptr<const int>>’ requested

...and on oic2 you get:

conversion from ‘std::experimental::optional<std::shared_ptr<int>>’ to non-scalar type ‘std::experimental::optional<std::shared_ptr<const int>>’ requested

Similar arguments apply for cases like:

class Foo {};
class Bar : public Foo {};

optional<unique_ptr<Foo>> makeOptionalFoo() {
    return unique_ptr<Bar>(new Bar);
}

Which doesn't currently work, but I think it should.

How to set an optional

I am trying to migrate a project using boost to C++11 and I am using this . But I am getting this error

error: no match for ‘operator=’ (operand types are ‘std::experimental::optional<std::__cxx11::basic_string<char> >’ and ‘char*’)

When I simply set my optional<T> using datadir = argv[++i];.

How can I set a optional<T>

misbehaves in presence of overloaded operator,

Line 116:
template <class X, class Y, size_t S = sizeof((std::declval() = std::declval(), true)) >

... would make use of an overloaded operator, on the result of the assignment. Suggestion: either cast the result of the assignment to void, or use class Z = decltype(... = ...) instead of the third template parameter.

move operators

I'm probably abusing the issue system, but I had another question regarding to the design.

Why does the move constructor and move assignment operator leave the value of the moved-from object defined? Other classes in the standard library typically end up in a "default constructed" state.

If you'd say that it doesn't really matter since in general you shouldn't rely on the state of a moved object I would agree, but it is not really consistent with the rest of the standard library.

Thanks,
Bert

VS2013 Support

Maybe you can add some support to VS 2013, which C++11 is almost there.

Issue with std::partition

On OSX, Xcode9.3, the following code fails to build:

#include <algorithm>
#include <vector>

#include "optional.hpp"
namespace tr2 = std::experimental;

int main(int argc, const char* argv[]) {
    auto vec = std::vector<tr2::optional<int>>{};
    std::partition(begin(vec), end(vec), [](const auto& val) { return val; });
    return 0;
}

Errors:
optional.hpp:489:102: Exception specification of 'swap' uses itself
optional.hpp:489:122: Too many arguments to function call, expected single argument 'rhs', have 2 arguments

Typo in feature guard macros

There's a typo in the header's feature macros. HIGHER is spelled "HIGHTER".
At first I was worried of the typo leading to some bugs, but it seems to be coherently misspelled in the whole header so it's ok.

Nevertheless, I felt like reporting it would be useful anyway...

On line 45:

# if defined __clang_major__
#   if (__clang_major__ == 3 && __clang_minor__ >= 5)
#     define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
#   elif (__clang_major__ > 3)
#     define TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
#   endif
#   if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_
#     define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
#   elif (__clang_major__ == 3 && __clang_minor__ == 4 && __clang_patchlevel__ >= 2)
#     define TR2_OPTIONAL_CLANG_3_4_2_AND_HIGHER_
#   endif
# endif

On line 87:

# if defined TR2_OPTIONAL_CLANG_3_5_AND_HIGHTER_ && (defined __cplusplus) && (__cplusplus != 201103L)

Future proof #include

What is the best way to include akrzemi1/Optional in such a way that it is future proof and if/when the compiler has std::optional support that version will be used?

Can the #include be completely bypassed (using macros) or does the implementation simply fall back on the std one if it exists?

-Werror=sign-conversion on `fail()`'s unsigned line number

Hey there. I've actually still got a C++11 project that has a dependency on this optional.hpp... and don't want to bump the project to C++17. So this still seems the best canon source for the file.

In the compiler settings this has -Werror for all warnings as errors, and then among flags it checks is -Wsign-conversion. Here fail() takes in an unsigned and passes it to __assert( ):

inline void fail(const char* expr, const char* file, unsigned line)

FWIW, the definition in <assert.h> that I have on the machine (in gcc 4.9.2-10 and clang 3.5.0-10) is:

/* The following is not at all used here but needed for standard
   compliance.  */
extern void __assert (const char *__assertion, const char *__file, int __line)
     __THROW __attribute__ ((__noreturn__));

It's easy enough for me to change. But as I'm leaving notes in the file saying where it came from, it would be nice if it "ran unmodified" so that if it were pulled down from git again one wouldn't have to figure out what the error is. (The person doing that and getting confused would most likely just be me, later. :-) But it could be someone else.)

What I'd do would be just take a signed int to fail(), due to the seemingly-prevailing wisdom that unsigned integers aren't worth it:

http://stackoverflow.com/questions/10168079/why-is-size-t-unsigned

Or it could be cast...

Library does not compile with G++ under OS X

With G++ version 4.8 or 4.9 on OS X, installed from Homebrew, the library does not compiler:

optional.hpp: In function 'void std::experimental::fail(const char*, const char*, unsigned int)':
optional.hpp:211:29: error: '_assert' was not declared in this scope
     _assert(expr, file, line);

If I add an underscore to call __assert instead of _assert everything works. It seems that it fails to recognize that it is using the GNU library

No convenience function for making optional<T&> from optional<T>

Currently the only way to make an optional<T&> from an optional<T> is a ternary expression passed to an explicit constructor:

optional<A> a = ...;
myfunc(optional<A&>(a ? *a : nullopt));

I wouldn't suggest automatic conversion, but explicit conversion would be nice:

myfunc(optional_cast<A&>(a));

What say?

Compilation fails with CUDA 8.0 nvcc and GCC 6.2.1

I've been happily using this class with CUDA 7.5/8.0 and GCC 4.9.3 for a while. Now I'm trying to upgrade to GCC 6.2.1, and I'm getting compilation errors. They do not occur when just compiling with GCC 6.2.1 directly - only when compiling via nvcc. See my Stackoverflow question on this matter.

A minimum working (or rather breaking) example:

Code:

#include "optional.hpp"
int main() { return 0; }`

Compilation command:

nvcc -std=c++11 -Xcompiler -D__CORRECT_ISO_CPP11_MATH_H_PROTO -Wno-deprecated-gpu-targets -o a a.cu

remove_reference => decay

According to the Library TS
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4529.html#optional.object.assign
The assignment operator C++ template <class U> optional<T>& operator=(U&& v); shall not participate in overload resolution unless C++ is_same_v<decay_t<U>, T> is true.

The current reference implementation however uses remove_reference and not decay:

 template <class U>
  auto operator=(U&& v)
  -> typename enable_if
  <
    is_same<typename remove_reference<U>::type, T>::value,
    optional&
  >::type

Make a partial specialization of `std::optional<T&>` which essentially implements as `T*`?

Hi, thanks for publicizing this, I have been using a version of optional derived from this in a few projects and it has worked excellently for me.

One thing I wanted to suggest:
I noticed that in your optional type, unlike in boost::optional (iirc), it is legal to take an optional over a reference type, e.g. std::optional<T&>. For various reasons I sometimes find this preferable to the more traditional but semantically very similar T* -- in particular, optional indicates clearly to the programmer that the value might be vacant and that they should expect this, also, occasionally I write code that treats any optional<T> type a certain way. For instance a template function which takes a series of types, might assume that an optional<T> indicates that an error encountered while obtaining a value in some context should not be fatal, while in other cases that error should be logged / propagated etc.

However, a drawback is that std::optional<T&> may take up more space than a T*, since it requires a bool. If the memory must be aligned then it may double the space I suppose.

A natural idea then is that in case that the template parameter is a reference type, the std::optional template class should select a different optional_base type which uses T* to represent the value, and nullptr to represent vacancy. Since nothing can be legally placed at the null address anyways...

I am thinking to tweak the version used in one of my projects in this manner, but I would like to hear what you think about it / if you anticipate any problems.

Thanks also for writing your blog, by the way.

Add a has_value() method

C++14's std::experimental::optional was missing the useful (public) method has_value(), which is essentially an exposure of (the private) initialized() method. Shouldn't this optional implementation also have it?

Does not work without explicit initialization on constructor on nvcc

If you attempt to put optional in a struct which is used from a cu file (compiled by nvcc), you may get this error:

Error: Internal Compiler Error (codegen): "there was an error in verifying the lgenfe output!"

A minimal reproduction is this program:

#include "Optional.hpp"

struct O {
  O() {} // required!
  std::experimental::optional<int> x;
};

void blah() {
  O o;
}

compiled with nvcc -c main.cu -std=c++11 --expt-relaxed-constexpr (the --expt-relaxed-constexpr is mandatory).

There is a simple workaround for this problem: explicitly initialize all optional fields in your constructor.

PyTorch tracking issue: pytorch/pytorch#12117

misbehaves in presence of `void operator&()`

196:
template <class X, size_t S = sizeof(std::declval< X&>().operator&()) >

This is not selected if operator& exists but returns void. It's also not selected if the call to operator& is ambiguous or is deleted.

(Ultimately, the right fix here is to make std::addressof be constexpr; in Clang, you can implement constexpr_addressof using __builtin_addressof.)

Unfortunate macro names

The use of macro names REQUIRES and ASSERTED_EXPRESSION can break existing code, especially the former is quite likely to occur in real-world code as it did for me.

Please consider better names or not using macros for the few places where they are used. If you want to keep macros and just rename them, consider #undef-ing them at the end of the header.

Missing == operator overloading

The following code is not compiling

void foo( optional<unsigned short> opt ) {
  bool comp = opt == 0;
}

So looking at the comparison operator I wondered why there is no overload

template< class T, class U >
constexpr bool operator==( const id::optional<T>& opt, U&& value )

Is this not in the spec of rather not in this implementation?

EDIT:
Got the signature wrong.

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.