tech-userlevel archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: EV_SET() better C++ compat with alternative implementations



On Sun, Aug 11, 2019 at 03:57:50 +0200, Kamil Rytarowski wrote:

> On 11.08.2019 02:56, Valery Ushakov wrote:
> > Kamil Rytarowski <n54%gmx.com@localhost> wrote:
> > 
> >> Cast of udata from void* to intptr_t shall be done with
> >> reinterpret_cast<> otherwise a C++ compiler errors.
> >>
> >> Defining __REINTERPRET_CAST [1] and using it, did not work as a compiler
> >> protested for NULL argument "warning: passing NULL to non-pointer argument".
> >>
> >> Using double cast __REINTERPRET_CAST(intptr_t, __CAST(void *, (udata)))
> >> pacified the warning/error about passing NULL in C++, but it created the
> >> problem of calling EV_SET using the native argument type intptr_t.
> > 
> > You are reporting quite an abstract summary that is not so easy to
> > follow for someone who hasn't done all the same experiments that you
> > already have done.
> 
> 
> $ cat /tmp/test.cpp
> 
> 
> #include <sys/types.h>
> #include <sys/event.h>
> 
> int
> main(int argc, char **argv)
> {
>         struct kevent kv;
> 
>         EV_SET(&kv, 0, 0, 0, 0, 0, 0);
>         EV_SET(&kv, 0, 0, 0, 0, 0, NULL);
>         EV_SET(&kv, 0, 0, 0, 0, 0, nullptr);
>         EV_SET(&kv, 0, 0, 0, 0, 0, 0L);
>         EV_SET(&kv, 0, 0, 0, 0, 0, 0LL);
>         EV_SET(&kv, 0, 0, 0, 0, 0, 0U);
>         EV_SET(&kv, 0, 0, 0, 0, 0, 0UL);
>         EV_SET(&kv, 0, 0, 0, 0, 0, 0ULL);
>         EV_SET(&kv, 0, 0, 0, 0, 0, (intptr_t)0);
>         EV_SET(&kv, 0, 0, 0, 0, 0, (uintptr_t)0);
> 
> 
>         return 0;
> }

This is not really an answer I was expecting as you are still not
saying anything of substance and your readers still have to
second-guess.  Are you trolling?

I *guess* that the issue here is C++11 nullptr.  If that's indeed the
case why don't just use a template with explicit specialization for
nullptr_t?  Something along the lines of:

// c++ -S -O3 -std=c++11 -Wall -Wextra -Wold-style-cast ev.cpp
#include <sys/types.h>
#include <sys/event.h>

#if __cplusplus >= 201103L
#undef EV_SET /* from the header */

static inline void
EV_SET_(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter,
	uint32_t _flags, uint32_t _fflags, int64_t _data,
        uintptr_t _udata)
{
	_kevp->ident = _ident;
	_kevp->filter = _filter;
	_kevp->flags = _flags;
	_kevp->fflags = _fflags;
	_kevp->data = _data;
	_kevp->udata = _udata;
}

template <typename _U>
static inline void
EV_SET(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter,
       uint32_t _flags, uint32_t _fflags, int64_t _data,
       _U _udata)
{
    EV_SET_(_kevp, _ident, _filter, _flags, _fflags, _data,
	    static_cast<uintptr_t>(_udata));
}

/* specialize for std::nullptr_t */
template <>
inline void
EV_SET(struct kevent *_kevp, uintptr_t _ident, uint32_t _filter,
       uint32_t _flags, uint32_t _fflags, int64_t _data,
       decltype(nullptr) _udata __unused)
{
    EV_SET_(_kevp, _ident, _filter, _flags, _fflags, _data,
	    static_cast<uintptr_t>(0));
}
#endif

extern void consume(const struct kevent &kv);


int
main()
{
        struct kevent kv;

        EV_SET(&kv, 0, 0, 0, 0, 0, 0);
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, NULL);
	consume(kv);

#if __cplusplus >= 201103L
        EV_SET(&kv, 0, 0, 0, 0, 0, nullptr);
	consume(kv);
#endif

        EV_SET(&kv, 0, 0, 0, 0, 0, 0L);
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, 0LL);
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, 0U);
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, 0UL);
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, 0ULL);
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, static_cast<intptr_t>(0));
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, static_cast<uintptr_t>(0));
	consume(kv);

        EV_SET(&kv, 0, 0, 0, 0, 0, L'x');
	consume(kv);

        return 0;
}


-uwe


Home | Main Index | Thread Index | Old Index