GithubHelp home page GithubHelp logo

gsl's Issues

Works on FreeBSD 10.x

As requested, this is a report that the library builds and works with FreeBSD 10.x. The default system c++ compiler (clang 3.4) is too old, but installing the clang36 package and setting -DCMAKE_CXX_COMPILER=clang++36 or -DCMAKE_CXX_COMPILER=clang++37 when installing results in all tests passing.

Avoid the use of macros as Expected

Having macros that are not prefixed by the library name is a bad practice as in

#define Expects(x)  Guide::fail_fast_assert((x))
#define Ensures(x)  Guide::fail_fast_assert((x))

Usually we use UPPERCASE letters for macros.

In addition, we have inline functions in C++, so no need for a macro that call another function ;-)

Final_act can lead to program termination if the final act throws an exception

Final_act does not check that the object to be invoked is no-except invokable or try to catch any generated exceptions. This could be bad if multiple final acts are used to clear up state on scope exit.

Either Final_act should catch exceptions or there should be an requirement that the invokable object cannot throw exceptions when invoked. It may be desirable to have two implementations of Final_act:
Final_act and Final_act_noexcept which try and catch exceptions or do not depending on the noexcept status of the invokable object.

Design of Final_act is dependent on copy elision to avoid multiple 'final acts'

The move constructor does not flag the moved-from object as non-invokable

auto invocation_count = 0;
auto f = finally([&invocation_count]{ ++invocation_count;});
assert(invocation_count == 1);

If the copy-by-rvalue-reference is not elided (which is possible but not necessary) then the invocation count will be 2. The final_act object needs an internal bool to track its state or the C++ standard needs to require copy elision.

See: https://github.com/jbcoe/CppSandbox/blob/master/ScopeGuard/ScopeGuard.cpp

for a similar class.

Add generated files to .gitignore

I ran cmake to generate a VS solution and built, and got a ton of generated files not ignored by .gitignore. Would be good to add these files.

Reduce minimum required version of CMake for building

Is there any reason to require CMake 3.2.2? I tried to lower it to 3.0.0 (version I have on my machine) and gsl was built and passed all tests. It probably can be built with even older versions.

I can send a PR to lower it for 3.0.0 for now.

Prefix all the macros by GUIDE_

We can see the use of macros that can collide with the application macros as in

#if defined(SAFER_CPP_TESTING)

all the macros of the library must be prefixed by GUIDE_.

`as_array_view` for types with alignment requirement

array_view::as_array_view() for byte arrays should either be restricted to types without alignment requirement or verify at runtime that the data pointer is properly aligned. Otherwise (according to The Standard) reinterpret_cast may adjust the data pointer and I doubt this is the desired behaviour.

Use a specific version of unittest-cpp

Currently the README says to clone https://github.com/Microsoft/unittest-cpp, which means a given SHA of GSL may produce different test results on different days if/as unittest-cpp gets new commits.

Two related questions then:

  • can we use a git submodule to pin to a particular SHA of unittest-cpp? Or some other mechanism?
  • is Microsoft going to maintain its fork of unittest-cpp or is it upstreaming its changes?

coordinate_facade doesn't verify ValueType is unsigned

coordinate_facade has a static assert with the string: "ValueType must be unsigned integral type!", but it doesn't verify that ValueType is unsigned. If I change it to verify this it fails because array_view_tests use char.

Docs do not explain how to use the library

AFAICS the docs are not completely self-contained. At least I was not able to find out within 30 minutes how and when to use the library. I looked at https://github.com/isocpp/CppCoreGuidelines and still did not catch the idea. Are there any short examples?

I grabbed some ideas from the unit tests, especially as_array_view, but reading all unit tests to know about features like Expect may be error prone because someone probably confuses test features with GSL features.

Any docs available beyond https://github.com/isocpp/CppCoreGuidelines/blob/master/docs/Lifetimes%20I%20and%20II%20-%20v0.9.1.pdf ?

Another example: What is the semantics of maybe_null_dbg? Cannot grab it from this test:

    TEST(TestMaybeNull1)
    {
        int n = 5;
        maybe_null_dbg<int *> opt_n(&n);
        int result = 0;
        bool threw = false;

        CHECK_THROW(result = *opt_n, fail_fast);
    }

Final_act move constructor

Final_act(const Final_act&& other) : f_(other.f_) {}

Shouldn't that be:

Final_act(Final_act&& other) : f_(std::move(other.f_)) {}

GSL.assert macros should be methods

Considering the intent of Expects/Ensures to eventually be part of declarations, I can understand why they were made macros, but until a tool (or perhaps compiler extension, since I'm not sure it's possible to implement other than a namespace colliding macro?) actually supports placing them in a declaration, I think they would be better as functions.

As in the guidelines (ES.31), macros violate the usual scope rules, they can behave oddly with parameters, and they should be avoided unless necessary. Given this, I believe that as long as Ensures/Expects are being used in their current form, they would be better suited to functions.

does array_view assume "default char unsigned" ?

Problem when using unsigned char:
array_view.h(495): const char dynamic_range = -1;

Problem when using signed char, many of the following:
array_view.h(xxxx): warning C4245: 'initializing': conversion from 'const char' to 'const size_t', signed/unsigned mismatch

I'm not too keen on disabling the related warnings...

Missing directory unittest-cpp

The unites-cpp directory should be part of the main repository so that:
(1) git clone
(2) cmake configure
succeeds out of the box.

not_null<>: Missing assignment from related types ?

For not_null<>, if there's a constructor for related types:

template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null(const not_null<U> &other);

I would also expect the assigment:

template <typename U, typename Dummy = std::enable_if_t<std::is_convertible<U, T>::value>>
not_null<T> & operator=( not_null<U> const & other );

However it's not present.

The `final_act` helper function name `finally` is misleading.

The final_act helper function function, finally, is misleadingly named as it returns an object which, if not captured, will result in instant invocation of the given function object.

The following code looks correct but database lookups and insertions will fail as the 'final-act' was invoked at [1].

auto db_handle = my_db_api_open_db("My database name");
finally([db_handle]{ db_api_close_db(db_handle); }); // [1]
// do some lookups and insertions

I propose that finally is renamed to make_final_act or is replaced by a macro that captures the return value for the user into a uniquely named temporary variable (I prefer make_final_act).

add travis testing

I added travis testing for gcc5 and clang36 on my fork
I'm ready to send in a PR if I got approval for this issue.
Let me know I need to add more compilers and which ones.

Why does fail_fast_assert throw and not assert?

I know that people have different opinions about this, but in the design by contract community most people seem to adhere to this principle:
Use asserts for invariants, preconditions and postconditions. Use exceptions when user input is involved.

The purpose is to fail fast, and an assert is a way to fail faster since exceptions can be caught and hence worked around. People should never be able to work-around these invariants. If you fail to comply with the preconditions anything can happen (which I consider a good thing) and the implementations should not continue as if nothing happened.

If you follow this principle, Expects and Ensures should assert and not throw. It also means that you shouldn't put something in an not_null when it directly comes from the user (for example input data from a text file, something coming from an edit box, ...) since you are not sure that the precondition is fulfilled and hence it doesn't make sense to let not_null throw.

Some people also follow a slightly different variant: Use asserts for logic errors in your own code and exceptions when client code is involved. The different with the previous principle is that here the we are talking about client code and not user input. Since for example a not_null can be both used internally and at the border of the interface for the client you might want to use exceptions in for not_null when (and only when) client code is involved. In this case you might want to add a policy to these classes to be able to specify the desired fail behavior.

Anyway, since (some) people would like to be able to use these libraries without having exceptions, but have asserts instead, it makes sense to let the users to this library specify what should happen when the pre- and postconditions are not met. Next to the conceptual reasons there is also a performance reason. If the code is guaranteed not to throw more optimizations can be done.

Brace style is inconsistent.

There are places where we do

struct Foo {
...
};

And others where we do

struct Bar
{
...
};

We should pick one and stick with it.

Should not_null act like an alias

Right now it's implemented like a smart pointer, with method like get(), but if I'm reading the isocpp guidelines correctly it should act like an alias. Given that it's under GSL.Views with owner and not GSL.Owner with the smart pointers.

template <class T> using not_null = T;

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.