Coder Social home page Coder Social logo

sg14's People

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  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

sg14's Issues

CMake errors

Right now, it seems like cmake fails to find the plf tests. Commenting out this target works.

inplace_function implicit conversion chooses copy over move

This is a really unfortunate side-effect of a core language issue, IMNSHO; this week I have been actively working on trying to understand and diagnose the core issue. CWG 1579 is related but its resolution left much to be desired.

Consider this program:

using IPF20 = stdext::inplace_function<void(), 20>;
using IPF40 = stdext::inplace_function<void(), 40>;
static_assert(std::is_convertible<IPF20, IPF40>::value, "");

IPF40 foo() {
    IPF20 f;
    return f;  // HERE
}

What happens on the line marked "HERE"? Naively, we would expect NRVO (copy elision). But that can't happen because IPF20 and IPF40 are not the same type. So, post-CWG1579, we would expect lvalue-to-rvalue conversion — we'd expect that the expression f is treated as an rvalue, and the wrapped functor is moved from f into the return slot. However, CWG1579 kicks in only for constructors; it does not kick in for inplace_function's clever use of a templated conversion operator to implement implicit conversions. So CWG1579 does not kick in, and what we actually get in this case is a copy operation.

SG14 could fix this by changing the implementation of implicit conversions for inplace_function to use converting constructors instead of conversion operators, but this strikes me as a library fix for a language bug. I am pessimistic but not fatalistic that we might actually be able to get a core language fix here. I'm opening this GitHub issue just to document the issue for posterity.

(I remember remarking on @Voultapher's unusual and clever use of conversion operators at the time. He convinced me that it was the Right Way to do it, and I still think it is, really. But I'm sad to see that it actually does have minor negative consequences due to this core language bug.)

non thread-safe shared_ptr

Is there a chance to have a non thread-safe shared_ptr in the standard?

I was thinking either as a new template or maybe the current shared_ptr should have a template parameter if it's ref counting should be atomic.

There is quite a bit of interest in such a thing - see here

Andrei Alexandrescu talked at the cppcon how to implement such a pointer yourself but I feel the standard should provide one - see here

If facebook are doing it - it must be valuable.

Currently the only publicly available solution seems to be building boost with a flag/define to disable thread-safe reference counting.

It might be also good to have the optimizations that Andrei talks about - for the common case when the ref count only goes to 1 and then to 0.

I've already asked this in the google groups for the c++ standard/discussions and I was told that I should make a proposal but I'm not gonna go that route myself just yet.

[inplace function] Problems assigning if my starting point is empty/nullptr

Let's say I have a static inplace function:

static stdext::inplace_function<void(embvm::i2c::status)> twim0_callback;
static stdext::inplace_function<void(embvm::i2c::status)> twim1_callback;

Later I set the value:

twim0_callback = cb;

Under this scenario, I end up with a hard fault within operator=(const inplace_function&), on this line:

vtable_ptr_->destructor_ptr(std::addressof(storage_));

I don't actually have a vtable pointer at this time, according to gdb:

(gdb) p vtable_ptr_
$3 = (stdext::inplace_function<void(embvm::i2c::status), 32, 8>::vtable_ptr_t) 0x0

This confuses me, because it seems like I should be using the address of empty_vtable.

I'm encountering this with the following arm-none-eabi-gcc:

gcc version 8.2.1 20181213 (release) [gcc-8-branch revision 267074] (GNU Tools for Arm Embedded Processors 8-2018-q4-major)

Difficulty accessing SG14 from the web

As demonstrated here, SG14 is needs some changes in order to make it more accessible by more people. In particular, the three main audiences of the repository / organization are:

  1. developers using Git to collaborate on code and documents;
  2. the general public who may be curious about SG14 and wish to casually browse its associated documents and
  3. ISO C++ activity including submitting papers as files in specific formats.

GitHub is naturally better suited to 1), OK for 2) and troublesome for 3).

Suggested improvements include:

  1. a general reorganization which ensures that anyone can clone the repo and find all the pertinent documents in a single place;
  2. GitHub Pages to provide convenient URLs to browser-friendly document views and
  3. Packaged builds of documents in HTML / PDF format for submission to the committee etc..

[inplace_function] Ambiguous overloads.

Just hit an issue when overloading a function accepting inplace_function vs. std::function. The compiler (MSVC 2017, clang 7) cannot disambiguate by function arguments. Here is a repro example and a link to it on compiler explorer.

Not sure if there is something to be done about this, worth investigating though.

#include <cstdio>
#include <functional>
#include <sg14/inplace_function.h>

// Something to be done about this?

/**
 * Ambiguous
 */
void myfunc(stdext::inplace_function<void()>&& exec) {
    std::invoke(exec);
}
void myfunc(stdext::inplace_function<void(size_t)>&& exec) {
    std::invoke(exec, size_t(42));
}

/**
 * Not ambiguous
 */
void myfunc_std(std::function<void()>&& exec) {
    std::invoke(exec);
}
void myfunc_std(std::function<void(size_t)>&& exec) {
    std::invoke(exec, size_t(42));
}

int main(int, char**) {
    // ambiguous
    myfunc([](){
        printf("blee\n");
    });

    // ok
    myfunc_std([](){
        printf("blou\n");
    });

    return 0;
}

https://godbolt.org/z/38cCZz

Good day

Declaration ring_iterator friend operator+=()

Shouldn't the friend declaration of ring_iterator's operator+=() and operator-=() be

template< class R, bool C >
friend ring_iterator<R,C> & operator+=( ring_iterator<R,C> & it, int i ) noexcept;

template< class R, bool C >
friend ring_iterator<R,C> & operator-=( ring_iterator<R,C> & it, int i ) noexcept;

instead of

friend type & operator+=(  type & it, int i ) noexcept;
friend type & operator-=( type & it, int i ) noexcept;

GNU C++ 5.2 warns (-Wnon-template-friend)

inplace_function move constructor should be noexcept

Right now, the following program performs poorly:
https://wandbox.org/permlink/vLEl9Owmp1exrkKA

struct Widget {
    Widget() {}
    Widget(Widget&&) noexcept { puts("move"); }
    Widget(const Widget&) noexcept { puts("copy"); }
};

auto f = [w = Widget()]() {};
using IPF = stdext::inplace_function<void(), 32>;
std::vector<IPF> v;
v.emplace_back(f);
v.emplace_back(f);
[...]

The vector resize does copy instead of move, because inplace_function's move constructor is not marked noexcept, and vector is pessimized in that case.

I'd like to see us explicitly drop support for non-noexcept-moveable types, preferably by specifying that the move constructor will call std::terminate if the wrapped object throws during its move-construction. Then the patch to de-pessimize the vector code above would be a single keyword: just add noexcept to the move constructor. (And to swap; and optionally to move-assignment.)

@carlcook thoughts?

Make std::inplace_function a specialization of std::basic_function

This was feedback I received from Louis Dionne during the SG14 meeting at CppCon.

The idea is that with Folly (being a unique function), there might actually be lots of use cases of different storage types (and other behaviours), and then we will get an explosion of new types (e.g. std function, move-only function, inplace function). Maybe it is best to do what std::basic_string does, where Traits are used to provide the implementation details.

So basically the standard focuses on basic_function, and then inplace function is a second proposal that builds on basic function, providing traits where memory allocation is inplace.

slot_map: custom key causing clang to seg fault.

Hi,

I am trying to use slot_map with a custom key:

template <typename T>
class VariableKey : public std::pair<unsigned, unsigned>
{
    typedef T variable_type;
    // Slot Map key (index, generation).
    bool operator<(const VariableKey<T> &other)
    {
        this->first < other.first;
    }
};

This causes this error:

clang: error: unable to execute command: Segmentation fault: 11
clang: error: clang frontend command failed due to signal (use -v to see invocation)
Apple LLVM version 10.0.1 (clang-1001.0.46.4)
Target: x86_64-apple-darwin18.7.0
Thread model: posix
InstalledDir: /Library/Developer/CommandLineTools/usr/bin
clang: note: diagnostic msg: PLEASE submit a bug report to http://developer.apple.com/bugreporter/ and include the crash backtrace, preprocessed source, and associated run script.
clang: note: diagnostic msg: 
********************

PLEASE ATTACH THE FOLLOWING FILES TO THE BUG REPORT:
Preprocessed source(s) and associated run script(s) are located at:
clang: note: diagnostic msg: /var/folders/mm/mdrm14d96yqgjfyyfw6zyfq00000gn/T/TestSlotMap-cdca70.cpp
clang: note: diagnostic msg: /var/folders/mm/mdrm14d96yqgjfyyfw6zyfq00000gn/T/TestSlotMap-cdca70.sh
clang: note: diagnostic msg: Crash backtrace is located in
clang: note: diagnostic msg: /Users/kevinsheridan/Library/Logs/DiagnosticReports/clang_<YYYY-MM-DD-HHMMSS>_<hostname>.crash
clang: note: diagnostic msg: (choose the .crash file that corresponds to your crash)
clang: note: diagnostic msg: 

********************
make[2]: *** [tests/CMakeFiles/runTests.dir/TestSlotMap.cpp.o] Error 254
make[1]: *** [tests/CMakeFiles/runTests.dir/all] Error 2
make: *** [all] Error 2

[inplace_function] Giant Sized Buffers Required for Compilation

I can generate some example cases if you guys are unaware of this circumstance, but just wanted to bring it up to confirm.

All my inplace functions are usually at most a few hundred bytes, but sometimes in order to compile one will suddenly require like 10,000 bytes! (so about 2 orders of magnitude more space). I suspect it's when you have inplace functions inside inplace functions (but leaving certainty on that aside for now).

[inplace_function] Const-callability means thread-safety

Right now, inplace_function permits

auto lam = [i=0]() mutable { return ++i; };
const stdext::inplace_function<int()> f(lam);
f();

That is, if I have a reference to a const inplace_function, I can call its operator(), which can mutate its internal state, even though I've promised not to modify it!

I believe we ought to follow the lead of Folly::Function, fu2::function, etc., and split inplace_function into two kinds of specialization:

  • inplace_function<R(As...)> is constructible from either const-callable or non-const-callable lambdas, and provides only operator() (non-const)

  • inplace_function<R(As...) const> is constructible only from const-callable lambdas, and provides only operator() const

In this paradigm, you would not be permitted to write

int one(const inplace_function<int(int)>& f) {
    return f(1) + f(2);
}
int two() {
    auto mutlambda = [i = 0](int j) mutable { return i += j; };
    return one(mutlambda);
}

The call to f(1) would fail to compile because inplace_function<int(int)>::operator()(int) is not const-qualified. Instead, you would have to write either

int one(const inplace_function<int(int) const>& f) {
    return f(1) + f(2);
}
int two() {
    int i = 0;
    auto nonmutlambda = [&i](int j) { return i += j; };
    return one(nonmutlambda);
}

or

int one(const inplace_function<int(int) const>& f) {
    return f(1) + f(2);
}
int two() {
    auto mutlambda = [i = 0](int j) mutable { return i += j; };
    return one(std::ref(mutlambda));
}

or

int one(inplace_function<int(int)> f) {
    return f(1) + f(2);
}
int two() {
    auto mutlambda = [i = 0](int j) mutable { return i += j; };
    return one(mutlambda);
}

depending on the semantics you want.

Please make me a WG21-SG14 organisation owner

Sorry for putting this issue on the SG14 repo, I couldn't see a good place on github to otherwise post a message to @WG21-SG14/sg14, as suggested last July in https://groups.google.com/a/isocpp.org/d/msg/sg14/1yRloYFAkhs/Aq91OGjcBQAJ

Now that I have https://github.com/TBBle/SG14-comparing-virtual-functions functional, I have decided it makes more sense for the master copy (i.e. the one with github pages and an Issue Tracker) to be under the WG21-SG14 organisation.

According to https://help.github.com/articles/transferring-a-repository-owned-by-your-personal-account/ this means I need "admin or owner" permissions with the receiving organisation.

If there's any concerns, I'm happy to subsequently be restricted to admin permissions on this specific repo once it's moved.

On the other hand, you may also consider this an offer to volunteer for organisation maintenance duties. ^_^

[inplace_function] Should [](){return 42;} be convertible to inplace_function<void()>?

Related to #149.

static void test_void_returning_function()
{
    stdext::inplace_function<void()> f = []() { return 42; };
    f = []() { return 42; };
    f();
}

The above test case currently does not compile. Clang's error message is:

In file included from inplace_function_test.cpp:2:
../SG14/inplace_function.h:105:15: error: void block should not return a value
            { return (*static_cast<C*>(storage_ptr))(
              ^
../SG14/inplace_function.h:211:31: note: in instantiation of function template specialization 'stdext::inplace_function_detail::vtable<void>::vtable<(lambda
      at inplace_function_test.cpp:412:42)>' requested here
        static const vtable_t vt{inplace_function_detail::wrapper<C>{}};
                              ^
inplace_function_test.cpp:412:42: note: in instantiation of function template specialization 'stdext::inplace_function<void (), 32,
      16>::inplace_function<(lambda at inplace_function_test.cpp:412:42), (lambda at inplace_function_test.cpp:412:42), void>' requested here
    stdext::inplace_function<void()> f = []() { return 42; };
                                         ^

If we fix #149, then we must make a design decision here: should this code compile (as it does with std::function), or should it fail to compile (because returning 42 from a function with signature void(int) usually indicates a programming error)? https://quuxplusone.github.io/blog/2019/01/06/hyper-function/ is related.

[inplace_function] usage at shared library boundaries

Seeing as inplace_function is standard layout and cannot allocate, I assumed it would be safe (dependent on what is put in it, of course) to be used across shared library interfaces. Apparently this is not the case.

The mechanism used to identify an empty inplace_function relies on taking the address of an inline constexpr global. Perhaps this is specific to MSVC (obviously this is not specified by the standard), but in practice I'm seeing a default constructed function converting to false in one module, but to true (callable) in another module due to differing addresses of empty_vtable.

Is usage across shared libraries a bad idea in general and intentionally not supported? If not, is this something that can be easily addressed?

Invalid platform toolset?

My copy of Visual Studio 2015 does not accept the toolchain specified in the vcxproj files. It states that the given toolset is not installed. If I change the toolset back to just v140 as it used to be instead of Visual Studio 2015 (v140) then it works properly.

Improve memory algorithms with type traits

Couldn't the memory algorithms take advantage of type traits to avoid performing unneeded operations? For example, it should be possible to use tag dispatch on std::is_trivially_destructible in destruct to turn it into a no-op when T is indeed trivially destructible. Also uninitialized_move could take advantage of std::is_nothrow_move_constructible to get rid of the exception handling when it's unneeded and could even fall back to std::memmove when std::is_trivially_move_constructible is true.

I guess that compilers can already perform some of these transformations, but I know that at least libc++ tends to use tag dispatch in such cases anyway. On the other hand, I could understand that this repository provides proof-of-concept algorithms and not state-of-the-art ones, but if anyone wants to just use them a is, it might be a valuable addition.

volatile inplace_function fails to compile

If you declare a volatile inplace_function<...> variable you cannot call any or almost any methods on it, including operator()(), bool operator(), etc., presumably because volatile overloads for those are missing and the compiler refuses to use any overloads not marked volatile.

As you have probably guessed, I do bare metal programming and the variable I want to make volatile is accessed both from thread mode and an interrupt handler (for example, a timer interrupt calls a callback stored in a variable and sets it to empty). While I'm admittedly not entirely sure how necessary it is (it probably depends on many factors), this is a very common practice in embedded programming and I don't feel safe having to omit volatile. I see that there is effort being made to support embedded environments (e. g. 3b81451) which is a very good sign from my perspective. Would you be willing to consider adding volatile overloads?

[inplace_function] make it usable without exceptions

The throw std::bad_function_call(); in the default constructor of vtable causes compilation failures when building with -fno-exceptions.

What to do instead, I don't really know, but one of the use-cases I have for this is in an embedded setting and this is throwing a wrench in that unfortunately.

Linker errors when using cmake

Maybe I'm doing something wrong, but...

CMakeFiles/sg14.dir/home/carlcook/workspace/sg14/SG14/SG14_test/main.cpp.o: In function `main':
main.cpp:(.text+0x10): undefined reference to `sg14_test::transcode_test()'
main.cpp:(.text+0x15): undefined reference to `sg14_test::ring_test()'
main.cpp:(.text+0x1a): undefined reference to `sg14_test::thread_communication_test()'
collect2: error: ld returned 1 exit status
CMakeFiles/sg14.dir/build.make:172: recipe for target 'sg14' failed
make[2]: *** [sg14] Error 1
CMakeFiles/Makefile2:67: recipe for target 'CMakeFiles/sg14.dir/all' failed
make[1]: *** [CMakeFiles/sg14.dir/all] Error 2
Makefile:83: recipe for target 'all' failed
make: *** [all] Error 2
~/workspace/sg14/SG14/cmake (master *)$ 

License is missing on some includes

Currently there is no licensing information for algorithm_ext.h ring.h and transcode.h. This should probably be added if the code should be used by others.

[inplace_function] Opt-in "safe" default constructed inplace_function

At the moment a default-constructed inplace_function is not safe to call (depending on SG14_INPLACE_FUNCTION_THROW). IMO it would be interesting to be able to opt-in to a behaviour where at least inplace_function<void(...), ...> can be safely used from default-constructed instances. Optionally (or a second opt-in?) where inplace_function<R(...), ...> returns std::declval<R>() would potentially be interesting as well.

[slot_map] R1/R2 criticisms

I would like to challenge some decisions made in P0661r1 from SG14.

P0661r2 states the following question was asked and answered.
R1 | Should raw access to the underlying container be provided? | No. | SG14

This is inconsistent with the current behavior, as the container returns the underlying container iterators. This means you already have access to the underlying container either through begin and end.
I believe const access to the underlying container should be available, at a minimum. I would prefer full access to the underlying container. See my next contention point for more details on why this is preferred.

Another decision I would like to challenge is direct access to the underlying container iterators.

It also provides the following iterator type aliases. Note that the adapted container must provide iterators satisfying the constraints of RandomAccessIterator.

using iterator = typename Container<value_type>::iterator;
using const_iterator = typename Container<value_type>::const_iterator;
using reverse_iterator = typename Container<value_type>::reverse_iterator;
using const_reverse_iterator = typename Container<value_type>::const_reverse_iterator;

The access to the underlying container iterators is dangerous. I've already shot myself in the foot assuming coherent behavior between slot_map iterators and its keys. I believe many more will.

Furthermore, it precludes using standard algorithms like std::partition. I fear the slot_map api will grow, with many custom cases that will need special implementations. It is already starting : #133

An alternative would be to provide custom, "smart and safe", iterators that do not invalidate the relationship between keys and elements stored in the container. Iterator swap, for example, should swap elements and shouldn't invalidate keys. In fact, no iterator operation should invalidate keys, ever.

This may make slot_map iterators heavy or less performant (TBD in test implementation), which may be a problem. Again, I believe direct access to the underlying container would be a better way to deal with this issue. When a user accesses the underlying container, it is clear he is in "no mans land". When you use slot_map iterators, operations should be safe, always.

Currently, using slot_map iterators is no mans land... Yet SG14 doesn't agree underlying container access is a good idea. This doesn't seem coherent.

I would appreciate some feedback on the types of pitfall you may fall into with custom iterators.

Thank you, looking forward to your feedback.

Provide CMake & Conan installation support

It would be very useful to have proper CMake installation support for the library. Then Conan support would also be trivial to add. Currently we have to fork the repo and write our own custom wrappers over SG14 or even copy the headers directly which is suboptimal since we then have to sync with the upstream version manually.

Build fails (on gcc 5.4)

... due to something in the ring buffer:

In file included from /home/carlcook/workspace/sg14/SG14/SG14_test/SG14_test.cpp:6:0:
/home/carlcook/workspace/sg14/SG14/cmake/../SG14/ring.h:119:44: error: friend declaration ‘sg14::ring_iterator< <template-parameter-1-1>, <anonymous> >::type& sg14::operator+=(sg14::ring_iterator< <template-parameter-1-1>, <anonymous> >::type&, int)’ declares a non-template function [-Werror=non-template-friend]
   friend type& operator+=(type& it, int i) noexcept;
                                            ^
compilation terminated due to -Wfatal-errors.

inplace_function: unit test for functor copy-assignment that throws

On #116 @Voultapher writes:

@Quuxplusone thanks for your feedback so far! Something I noticed looking at the libcxx implementation, they seem to set their version of a vtable to 0, aka empty state, whenever they are about to copy or move. My best guess is, that its stack unwinding related. Can you come up with a test of a throwing copy assignment, that checks if the cleanup is done right?

I have been procrastinating on this. Creating this issue now so that it will not fall through the cracks when #116 is closed/merged.

[slot_map] Can you get a key using an iterator?

I'm trying to find the keys of stored objects that match a given predicate. I can't see any api to get a key from an iterator, but I may be missing something.

Is it possible to get a key using an iterator in slot_map?

Switch to a real unit-test framework

A problem I just discovered with the current assert-based testing is that the tests disappear in Release (or RelWithDebInfo) builds.

I'd suggest Catch since it's single-header, has reasonable clear syntax, and supports good DRY behaviours and BDD terminology.

I'm also happy to go ahead and do the conversion, this would help clean-up the current tests which are lumped together into a single executable, and one test currently prompts the user for input.

I'd probably go ahead and restructure the CMake a bit too, to take advantage of unit-testing support and allow testing individual tests. Currently compile failures in one test block the other tests completely.

inplace_function copy-assignment fails

https://wandbox.org/permlink/nT7NOhnVm2JZopjh

stdext::inplace_function<void(), 16> f;
f = []() { puts("hello world"); };
stdext::inplace_function<void(), 16> g;  // bonus: change 16 to 17 and it should still work
g = f;  // ERROR!

Oddly, it does work for move-assignment!
I think the issue is some SFINAE on the wrong overload. Should be:

template<typename Callable, class = typename std::enable_if<!std::is_lvalue_reference<Callable>::value>::type>
inplace_function& operator=(Callable&& target)

That SFINAE looks sketchy to me anyway, but it seems to DTRT.

`sg14::ring_span`: clear () member function gone awol

Maybe I'm missing a point, but having a clear() member function seems rather useful [popping them one by one vs. doing it O(1)] to me. Iff the sg14::ring_span would be assignable, I could do without, but that doesn't seem to be the case either. It is assignable, but not how I tried to do that. So if I have a sg14::ring_span as a class member, the only option is to pop till it drops :-) .

[slot_map] constructors

Currently, slot_map doesn't have many constructors one has come to expect. Adding slot_map(size_type count) and slot_map(size_type count, const T& value) would rank top for my needs. Eventually, mimicking applicable std::vector constructors would be welcome.

What is the state of a moved-from inplace_function?

Both folly::Function and fu2::function, as far as I can tell, make the following test case pass:

function<void()> foo = SomeFunctor{};
function<void()> bar;
assert(!bar);
bar = std::move(foo);  // move the state from foo to bar...
assert(!foo);  // ...leaving foo empty. (This assertion fails with inplace_function.)

To make this test case fail, you have to leave foo in a sort of "partly moved from" state, where calling foo() effectively has undefined behavior (because the contained SomeFunctor object you're calling is in a moved-from state), which kind of defeats the purpose of having an "empty" (bad_function_call-throwing) state at all.

On the other hand, if you do make this test case pass, then you end up with a strongly type-safe object type, where the object is fundamentally not allowed to enter a "nonsense" or "partly-moved-from" state. This strikes me as a good idea. I think inplace_function should follow the example of Folly here, and make this test case pass.

Compilation fails under VS2015 community ed.

The following test fails for me locally:

 static_assert(safe_add<std::uint8_t, -4>(15, 13).get<int>() == 28, "sg14::safe_add test failed");

C:\Dev\sg14\SG14\SG14\fixed_point.h(615): error C2338: mismatched safe_add parameters
C:\Dev\sg14\SG14\SG14\fixed_point.h(623): note: see reference to function template instantiation 'RESULT_TYPE sg14::_impl::add<RESULT_TYPE,REPR_TYPE,-4,int>(const HEAD &)' being compiled
with
[
RESULT_TYPE=output_type,
REPR_TYPE=uint8_t,
HEAD=int
]
C:\Dev\sg14\SG14\SG14\fixed_point.h(632): note: see reference to function template instantiation 'RESULT_TYPE sg14::_impl::add<output_type,REPR_TYPE,-4,sg14::fixed_point<REPR_TYPE,-4>,int>(const HEAD &,const int &)' being compiled
with
[
RESULT_TYPE=output_type,
REPR_TYPE=uint8_t,
HEAD=sg14::fixed_point<uint8_t,-4>
]
......\SG14_test\fixed_point_test.cpp(223): note: see reference to function template instantiation 'sg14::fixed_point<REPR_TYPE,-3> sg14::safe_add<uint8_t,-4,int>(const sg14::fixed_point<REPR_TYPE,-4> &,const int &)' being compiled
with
[
REPR_TYPE=uint8_t
]
......\SG14_test\fixed_point_test.cpp(72): note: see reference to class template instantiation 'sg14::fixed_point<uint8_t,0>' being compiled

[slot_map] partition and underlying_swap

When using slot_map for components and such, one would usually implement a disable feature. This is done using a pivot, and swapping disabled elements to the end of your contiguous container. Iterating the "enabled" data will thus be contiguous.

I don't think the standard would ever accept a container with this kind of state. So a way to enable this should be provided. From my uses so far, I think a simple id_swap(Key old, Key new) would enable a lot of needed flexibility.

For disabling components, one could create 2 slot_maps, enabled and disabled, and move objects between the 2. The only problem then is users will have copies of the original id. Adding id_swap lets you move into a disabled slot_map, swap the id to the old one, never invalidating user owned ids.

There are other uses for id_swap. When using RAII to keep user ids valid, the copy constructor would need such a thing.

Ultimately, you want to keep iterators valid when moving/swapping/deleting objects. id_swap is just an idea, there may be better ways.

inplace_function doesn't handle arguments with rvalue references well

For example, see here: https://godbolt.org/z/U3a2GX

#include <string>
#include "inplace_function.h"

std::string global_dummy;
void take(std::string&& s)
{
    global_dummy = std::move(s);
}

int main() 
{
    /// comment this and uncomment the std::function line to make it compile
    stdext::inplace_function<void(std::string&&)> func(take);
    //std::function<void(std::string&&)> func(take);

    std::string s = "1234567";
    func(std::move(s));
}

This code works as expected with std::function, but doesn't compile with inplace_function, complaining that (exact phrasing depends on compiler, but the same error message appears in all of them):

error: cannot bind rvalue reference of type 'std::__cxx11::basic_string&&' to lvalue of type 'std::__cxx11::basic_string'

If I understand it correctly, the problem is that operator() can't use a forwarding reference for the function arguments because they are not deduced in the function (they are parameters of the class template).

The standard library implementations solve this somehow. This rabbit hole was too complicated for me to follow.

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.